ソフトウェアにおけるものつくりの変革 -HaskellとFPGAから見えてくる

ソフトウェアにおけるものつくりの変革
−Haskell と FPGA から見えてくる組込み系のものつくりの革新−
Innovation for Software Design and Imprementation by Haskell and FPGA
福良 博史
FUKURA Hirofumi
1.はじめに
れる。この指示の集まりをソフトウェアと呼ぶ。
高信頼ソフトウェアによるものつくりにつ
ソフトウェアは、コンピュータというハードウ
いて根本的に何が問題となっているかを検討
ェアに強く依存し、ハードウェアが無ければた
し、そのあるべき方向性を見極めていきたい。
だの紙くず同然となってしまう。パソコン、マ
はじめに、ソフトウェアによるものつくり
イコンも含め、現在使われている通常のコンピ
の大前提は何かと考えるとそれは現在のコン
ュータは、一般にはノイマン型といわれている
ピュータが挙げられる。このコンピュータを
部類に属する。
動かすためにはそれなりの「言語」が必須で
このノイマン型コンピュータは、どのように
あり、その言語をどのようなものにしたら良
して動いているかを考えてみる。このコンピュ
いかという努力がこの半世紀あまり続いてき
ータへの指示は、コンピュータのメモリー上に
ている。このなかで大きな流れとして、手続
人間が指示すべき命令をその実行してほしいと
き型の言語(imperative language)と関数型
考えた手順通りに記録しておき、コンピュータ
言語(functional language)の二種類に焦点
がその命令をひとつずつ取り出して実行するよ
を当てて双方の特徴を概観し、関数型言語の
うになっている。そしてその結果として人間が
今後の有効性を述べる。
指示した通りの仕事をこなしてくれる。
ハードウェアの世界では、メモリーが安価か
つ大容量となり、速度も高速化し、色々なノイ
2.1
アセンブラの出現
マン型コンピュータ用 CPU のチップが続々と
コンピュータのメモリー上に配置するための
でてきている。そして FPGA のように自分で
一番基本になる言葉を機械語と呼ぶ。人間はは
CPU のプロトタイプを製作できる環境も安価
じめ機械語を二進数の値そのままをを用いてメ
に調達できる素地が整ってきている。
モリー上に配置していた。これでは人間の労力
本論は、今後の高信頼性システムを製作して
が大変だと考え、アセンブラが出現してきた。
いくための一方法として関数型コンピュータを
アセンブラを使うことにより機械語と一対一対
検討していくために、調査・分析を行っている
応の人間が理解しやすい記号(これをニーモニ
内容の途中経過を紹介する。
ック
mnemonic
コードと呼ぶ)を用いて指
示を書き、それを機械が理解できる機械語に自
2.半世紀におよぶ言語の変遷
動的にコード化することが可能になった。
ソフトウェアによるものつくりについて従来
行われている方法論を整理するための一つの観
点として、プログラミング言語に焦点を当てて
考えてみる。
コンピュータが世に現れて半世紀以上が経過
2.2
手続き型言語の変遷
このアセンブラでも記述が未だ機械の言葉
であり人間の表現する言葉からは、かけ離れ
ており、記述が大変である。たとえば a+b を
した。コンピュータは、それまでの機械と異な
cに格納するような加算を行うのに、Load a、
り、人間から色々な指示を受けて仕事をしてく
Add b、Store c のような手順がアセンブラで
は必要になる。これが c=a+b のように表現で
ズ ア ッ プ さ れ た の は 、 1968 年 に Edsger
きれば、今まで以上に人間の思考に近づき便
Dijkstra が発表したレター(1)からである。この
利である。ということで高級言語と呼ばれる
中で、goto 文が、プログラムの理解の妨げに
各種言語が登場してくる。
なることを述べている。ここから goto 文論争
・1950 年代
が巻き起こり一時は goto 文が魔女狩りにあっ
最初に FORTRAN が出現する。
これは 1954
ているような状況が出現した。この後から出
年に IBM の John Backus により考案された
てきた言語は、例外処理または繰り返しのル
最初の高級言語といわれる部類の言語である。
ープからの脱出用の制御命令としての exit 文
1950 年代後半には ALGOL、COBOL が登場
等は許しても、無条件にどこにでも移動可能
する。
な goto 文は使えないように制限するようにな
・1960 年代
ってきている。
1965 年に IBM が PL/I を発表する。
・1970 年代
この手続き型の言語の本質は、goto 文論争
において明らかになってきたように、人間が
1970 年にはスイスのチューリッヒ工科大の
機械への命令・指示の手順を計画し、機械は
Niklaus Wirth が PASCAL を教育用に考案し
その手順通りに機械的に実行していくように
た。1973 年にはベル研の Dennis Ritchie らに
できている。まさにこの手順をプログラムす
よる C 言語が登場してくる。
ることの困難さから色々な問題が生じている。
・1980 年代
買い物をしてくれる二足歩行のロボットが
1983 年には信頼性を向上させる意味で抽象
居て、このロボットに頼んで、ジュースとり
データ型を考慮したオブジェクト指向言語の
んごを買ってくるように依頼する場合を想定
C++がベル研の Bjarne Stroustrup によって
してみる。このとき、機械的な手順とは、図
考案された。
2.1のようになると想定できる。これは、
・1990 年代
いわゆる、How を表現するための言語となっ
1990 年代に入り、サン・マイクロシステムズ
ている。この図の中の手順1と手順2でりん
社の James Gosling が、ポータブル性、ドキ
ごとジュースを買う順序は、必ずこの順序を
ュメント性などを向上させたオブジェクト指
いやでも守ることになる。先にジュースを手
向の言語 Java を考案した。
にし、後からりんごを手にすることは決して
以上は手続き型の言語の発展である。
起こらない。もしそのようなことが起こった
ならそれは何か「システム障害」が生じたこ
以上で概観した手続き型言語は、現在のビ
とになる。
ジネスアプリケーションおよび、組込み系ア
プリケーションのソフトウェア開発の現場で
使われている。手続き型の言語以外はほとん
ど使われていないといっても過言ではない。
・手続き型言語の問題点
近年、社会問題となった金融関連のシステ
ムトラブル、エレベータ制御のトラブルなど
を引き起こしているものはこのような環境の
もとでつくられたシステムである。
この手続き型言語の問題点が大きくクロー
図2.1 手続き型の How イメージ
手順1.りんごがあれば、
りんごを買う
手順2.ジュースがあれば、
ジュースを買う
2.3
5. 関数型プログラミング言語における不
関数型言語の変遷
関数型言語の歴史も古く、手続き型の高級言
必要な多様性を 軽減するものである
語の FORTRAN が出てから数年後に登場する。
・1950 年∼1960 年代
こと。
この決定に基づいてつくられた言語が純粋な
はじめに、関数型言語の LISP は、1958 年に
関数型言語と言われている Haskell 98 である。
MIT の John McCarthy 等によって考案され
この Haskell は、現在ネットワークを介在し
た。当初、紙の上でのラムダ算法の記法であ
たアプリケーションをはじめとしグラフィック
ったが、色々な経緯を経て 1960 年代にはプロ
を利用したゲーム等と多彩な応用例が出てきて
グラミング言語となる。
いる。
・1970 年代
関数型の言語のイメージを先ほどの買い物ロ
1974 年にエジンバラ大から ML という言語
ボットに当てはめると、図2.2のようになる。
が出てきた。
関数型言語は、コンピュータのメモリや CPU
図2.2 関数型の What イメージ
の資源を多く必要とするため、実用的ではない
規定1 りんごがあれば、
という傾向になり、一時期低迷していた。
りんごを買う
・1980 年∼1990 年代
規定2 ジュースがあれば、
1987 年に米国オレゴン州ポートランドにて、
ジュースを買う
関数型プログラミング言語の国際会議
Functional
Programming
Language
and
Computer Architecture(FPCA’87)が開催さ
これは、一見したところ図2.1と同じでは
れ、現実のアプリケーションを構築するための
ないかと思うかもしれない。しかし他への副
共通の関数型言語を作ることが決定された。
作用を持たずかつ、手順xを規定xとしたよ
この委員会の主要な目標は以下の5項目の制
約を満す言語を設計することにあった。(2) (3)
うに、順序を意識しない、というところが根
本的に手続き型言語と異なる。
1. 教えること、研究すること、大規模な
システムを構築することを含む 応用
に適するものであること。
2. 形式的な構文と意味論の公開をもって
完全に記述されたものであること。
2.4
副作用についての若干の考察
副作用(side effect)とは何か、そのイメー
ジを把握しやすいように図2.3を用いて考
えてみる。
この図では仮想的な手続き言語を用いる。
3. 自由に利用できるものであり、なんび
関数は、Main プログラムから呼び出された時
ともこれを実装することを許可され、
に動くものとする。この図の中の外部変数の
誰にでも配布することが許可されてい
値に注目する。
るものであること。
この図において外部変数は、関数を呼出す
前に初期化されており、関数f(x)の中で
4. 広く認められたアイディアに基づいて
いるものであること。
この外部変数の値を変更している。これを副
作用という。
この副作用と呼ぶ意味は、以下のようなプ
ログラムの動作から理解できる。
この Main プログラムを実行すると、2行目
と3行目の Print で何が表示されるか?
どちらも Print
f(3)となっているが、
結果は異なる。
なお、純粋な関数型言語は、手続き型のよ
うに値をセットするものではない。定義をし
ているのであるから、値は最初から最後まで
不変である。このように両者の考え方が根本
2行目の結果表示されるものは、
6 (←3×2×1)
となる。このとき、関数f(3)の実行中に図
的に異なる。このため、関数型言語において
は、副作用という状況がそもそも発生しない
ことになる。
2.3のbの行で、yの値が’1’から’―1’に変化
する。そのため次の3行目の結果は、
―6 (←3×2×(―1))
3.具体的な言語の例
アセンブラ、手続き型言語、関数型言語につ
となる。この二回目の関数の呼び出しによって、
いて具体的なプログラミングのコード例を比較
再度bの行が実行されyの値が’―1’から’1’に戻
してみる。
る。外見上同じ関数の実行をしたにもかかわら
ず、同じ関数から返却される値が異なる。これ
は、手順(実行順序)と副作用の相互作用によ
って必然的に生じる。
3.1
Z80 のアセンブラ言語の例
図3.1にアセンブラで1から10の和を
求める例を示す。各行の手続き概要は以下の
通り。アセンブラ自体は手続き型の構造とな
図2.3 副作用のイメージ
っている。
外部変数 y
――――――――――――
関数f(x)
図3.1
アセンブラの例
01. ORG 100H
a. x←x*2*y
02.
LD
b. y←y*(−1)
03.
SUB A
c.
04. LOOP: ADD A,B
Return x
B,10
――――――――――――
05.
DEC B
Main プログラム
06.
JR
NZ,LOOP
1.外部変数y=1
07.
LD
(SUM),A
2.Print f(3)
08.
HALT
3.Print f(3)
09.
ORG
200H
10. SUM: DEFS 1
11.
END
オブジェクト指向の基本的概念としてデー
タのカプセル化または抽象データ型という考
え方がある。この考え方は、副作用を無くす
01⇒プログラム開始番地を 100 番地とする
ことが前提となっていると考えられる。しか
02⇒レジスタ B に 10 をセットする
し現実の手続き型言語は一般に自分の外部を
03⇒アキュムレータ A をゼロ化する
見ることが可能な仕様となっている。この副
04⇒A←A+B (最初は 0+10、最後は 54+1)
作用があるのは一見ソフトウェアを組む現場
05⇒B←B−1
では便利である反面、多用すると信頼性・保
06⇒05 の結果 B≠0の場合は LOOP に行く
守性などをあやうくしかねない。
07⇒SUM←A
1から 10 の和を格納
08⇒プログラムの停止
図3.4
Haskell の実行例
09⇒和の格納域を 200 番地からとする
10⇒和の格納域の確保
11⇒言語記述の終了
C 言語(手続き型言語)の例
3.2
図3.2に C 言語で1から10の和を求め
る例を示す。各行の概要は以下の通り。
図3.2
C 言語で和を求める例
01. int main(void) {
02. int i,sum=0;
03. for (i=1; i<=10; i++)
04.
sum=sum + i;
05. printf ("sum=%d¥n",sum);}
以下に、関数型言語の特徴の再帰的な定義
を駆使したテキスト行数を勘定する場合の例
を二件示す。
01⇒主プログラムで引数を持たないと宣言
図3.5は、テキストファイルの行数を求
02⇒整数の i と sum をゼロとして初期化
めるプログラムである。ここでは、改行コー
03⇒i を 1 から 10 まで1ずつ増加させ
ドを「¥n」と記述している。
ながら 04 を繰り返す
04⇒sum←sum+i
(最初は、0+1、最後は 45+10)
05⇒求めた和 sum を出力
01⇒行カウント関数の引数が空≡ 0 行
02⇒同関数の引数の頭が改行コード
≡ 1 行と勘定し、
関数(引数は頭 1 文字除外)を呼ぶ
03⇒同関数の引数が空ではない
3.3
Haskell(関数型言語)の例
図3.3に Haskell で1から10の和を求め
≡ 行勘定せずに、
関数(引数は頭 1 文字除外)を呼ぶ
る例を示す。各行の概要は以下の通り。
と各々定義する。
図3.3
Haskell で和を求める例
この行数カウントは改行コードの数を勘定
01. sumFunc 0 = 0
することになる。つまり改行コードが無い文
02. sumFunc n = n + sumFunc (n-1)
字列は1行分あるとは看做さない。
01⇒関数 sumFunc 0 ≡ 0
02⇒関数 sumFunc n ≡ n + sumFunc (n-1)
と定義する。
(注)≡:左辺を右辺のように定義する意
図3.5 Haskell で行数を求める例1
01. linesCount []
=0
02. linesCount ('¥n':cs) = 1 + linesCount cs
03. linesCount (c:cs)
= linesCount cs
このプログラムを実行した結果を図3.4に
示す。ここでは、0から0の和、0から 3 の和、
図3.6は、テキストの最後が改行コードで終
そして 0 から 10 の和を求めた結果を示す。
了しなくても1行と勘定する場合のコードを例
示する。この場合は再帰の定義を駆使している。
安にはなり得ると考える。
まずここで取り上げた、1∼10 までの和を求
図3.6 Haskell で行数を求める例2
める問題を見てみる。この場合は、
01. linesCount str = lineHead str
・ アセンブラ言語の場合は、11 行
02.
・ C 言語の場合は、5 行
where
=0
・ Haskell の場合は、2 行
03.
lineHead []
04.
lineHead ('¥n':cs) = 1 + lineHead cs
となり、Haskell が他より少ない行数でプログ
05.
lineHead (c:cs)
ラムコードが書ける。
06.
lineOthers []
07.
lineOthers ('¥n':cs) = lineHead cs
ついての調査結果の中に興味深い報告書(4)があ
08.
lineOthers (c:cs)
る。この注目に値する結果を、表4.1に抜粋
= 1 + lineOthers cs
=0
= lineOthers cs
米国海軍関係におけるプログラミング言語に
して紹介する。報告書には言語が多々示されて
いるが日本で主に知られている言語を記す。
図3.6の定義の概要は以下のようになる。
03、06⇒行頭であれ、行頭以外であれ、
空の文字列は、0行とする
表4.1 米国海軍関係の調査による
ソフトウェア開発の評価例
言語
コード
行数
ドキュメント
行数
開発期間
(時間)
Haskell
85
465
10
Ada
767
714
23
Ada9X
800
200
28
1105
130
-(*2)
04⇒行頭が改行コードの場合は、1行とし
かつ、残りを再度行頭とする
05⇒改行コード以外の行頭も、1行とする
しかし、残りは行頭以外とする
07⇒行頭以外の中に改行コードがあれば、
それを除いた残りを行頭とする。
C++
(この行は、すでに 05 で勘定済の行な
Awk/Nawk
250
150
-(*2)
ので、ここでは勘定しない)
Haskell(*1)
156
112
8
08⇒行頭以外は常に、1 文字除き、
その残りを行頭以外とする
(ここでは、改行コードが来なければ、
結果的にその他の文字をすべて読み飛
ばしていることになる)
Haskell の場合、
「=」は代入や置換えではな
い。「A=B」とは「A を B と定義する」を意味
している。
4.言語による生産性の比較例
プログラムのコードの多さによる生産性の比
較は、本当に客観的な尺度といえるのかという
議論はある。たしかに数十行の差などは、本当
に差が意味を持っているのか、有意差があるの
かは議論の余地がある。しかし、ある程度の目
(*1)大卒で Haskell を 8 日間訓練しただけ
(*2)報告なし
この表からは、Haskell が他を圧している。
とくに注目すべき点は、最後の行の Haskell で
ある。これは、大卒で特別な訓練を受けず、8
日間 Haskell の訓練を受けた後同じ課題を行っ
た結果と言われている。
5.高品質ソフトウェアのものつくり
以上、いくつかの例で示したように、手続き
型言語は、「やりたいことの手順を間違えない
ように時間の順序を記述する」(How)ことが
求められる。これに対し関数型言語は、
「やりた
いことの定義を矛盾無く、条件に抜けがないよ
うに記述する」(What)ことが求められている。
今後信頼性の高いソフトウェアを構築してい
くためには、How を記述する言語から脱却し、
7.今後の課題
What を記述する言語に向かうことが必要では
これまでの検討経過を踏まえ、今後の計画テ
ないかと考えている。関数型言語において一番
ーマの大枠は以下のようになると考えている。
ネックだったと思われる資源の消耗の激しさに
(1) 関数型的な言語との親和性に富んだ機械
対しては、近年のハードウェアの高密度化によ
り問題点が減少してきている。そして高品質な
ソフトウェアを構築していくための形式手法
(数学の集合論や記号論理を基礎においてい
る)による設計・妥当性の証明などとの親和性
語の検討を行う
(2) (1)のプロセッサを具体的にFPGAに実装
して評価検討を行う
この前提として、過去のLISPマシン等
の調査も必要
(3) 関数型的な言語で、ソフトウェア開発が容
にすぐれている、と考えている。
易に行える言語の検討
(4) 開発した言語によって構築したソフトウ
6.組込み系のソフトウェア開発
現在Haskellによってパソコン上のシステム
ェアシステムの信頼性を形式的手法によ
って評価・検証するための方法論の検討
は開発例の蓄積が始まっている。
近年組み込み系のソフトウェア開発ニーズ
は増加傾向にある。組込み系のシステムは人体
(5) 各種情報 ( 9 )
(10) (11) (12) (13)
等調査・分析を
継続していく
に影響を与えたり、社会システムに致命的な打
(6) 以上の検討を重ねながら、その都度、プロ
撃を与えるような問題が増えてくる可能性が
トタイプを作成し試行を継続的に行う
高い。このような事態を避けるためには、高信
頼性ソフトウェア開発の方法論の確立が望ま
なお、これらの課題を総て具体的に推し進め
ていくのは並大抵なことではない。このため、
れるようになってくると思われる。
この課題に対応するためには、従来の開発技
(4)の評価・検証の方法論を見据えながら、土
法のみならず関数型言語のようにWhatを定義
台となる(1)の関数型のプロセッサの検討に重
するような形態の開発環境の整備が必要とな
点を置いていこうと考えている。
ってくると考える。
現在の技術水準から考えると、CPUを独自
に試行錯誤しながらつくることは技術的にと
いうより、コスト的に困難であると考える。し
かし、FPGA(Field Programmable Gate
Array)等を利用することにより実験的なプロ
セッサを作成し、実験を試行錯誤に行い、調
査・分析を行う環境は整ってきている。たとえ
ば、Altera社が提供しているNIOSⅡ (5) および
Xilinx社が提供しているMicroBlaze (6) につい
ては、itronフリー版のTOPPERS (7)
(8)
なども
用意されている。
このような状況にあるため、根本的に新し
いプロセッサ(つまり新しいCPUと機械語)
を考えていく素地が出来つつあると考える。
参考文献
1) Edsger W. Dijkstra, Communications of
the ACM, Vol. 11, No. 3, March 1968, pp.
147-148
2) http://haskell.org/onlinereport/
3) http://www.sampou.org/haskell/report-re
vised-j/preface-jfp.html
4) http://www.mcs.vuw.ac.nz/courses/COMP
432/2006T2/docs/HaskellvCjfp.pdf
“Haskell vs. Ada vs. C++ vs. Awk
vs. ...An Experiment in Software
Prototyping Productivity”,1994
5) http://www.altera.co.jp/products/ip/proces
sors/nios2/ni2-index.html
6) http://www.xilinx.co.jp/ipcenter/processor
_central/microblaze/doc/mb_tutorial_c2bi
ts.pdf
7) http://www.toppers.jp/press/release-05041.pdf
8) http://www.ertl.jp/~honda/microblaze/ind
ex.html
9) http://glew.org/nglew/papers/talx86-wcsss
.pdf
“TALx86: A Realistic Typed Assembly
Language”
10) http://homepages.inf.ed.ac.uk/da/papers/
hbal/hbal.pdf
“Heap Bounded Assembly Language”
11) http://directory.fsf.org/devel/prog/Other_p
rogramming_languages/hla.html
“High Level Assembly Language - Helps
advanced Assembly programmers write
better code”
12) http://en.wikipedia.org/wiki/SECD_machi
ne
13) http://citeseer.ist.psu.edu/cache/papers/cs
/15301/http:zSzzSzresearch.microsoft.co
mzSzUserszSzlucazSzPaperszSzCompili
ngML.A4.pdf/cardelli84compiling.pdf
“Compiling a Functional Language”
14) http://lml.ls.fi.upm.es/~jjmoreno/paper_a
b.html
“Integration of Paradigms”