はじめに
プログラマは計算機に対して、「別に凝ったをやれとは言わないが、自明なことはやってくれよ」と思うものだ。例えば規則格子における差分法、特に陽解法は、式と差分方式さえ決まれば、(最適化とか考えなければ)後は自明なコーディングになる。さらに、領域分割による分散メモリ並列を考えた時、(効率とか考えなければ)やはり自明なだけで面倒なコーディングをする必要がある。
こういう「自明かつ面倒なコーディング」をやらなければいけなくなった時、「自動化したい」と思うのは自然な発想だ。Formuraは、まさにそのような思想で作られた、格子計算プログラム生成言語(というかフレームワーク)である。
本稿では、このFormuraを使ってみる。
インストール
Formuraは(おそらくオリジナルの作者の趣味で)Haskellで書かれている。なので実行にはHaskellが必要だ。例えばMacOSでbrewを使うなら
brew install haskell-stack
Linux系なら
curl -sSL https://get.haskellstack.org/ | sh
とかで入ると思う。
次に、Formuraをダウンロードして、セットアップしよう。
git clone https://github.com/formura/formura.git
cd formura
stack install
最後のstack install
は、初回実行時にかなり時間がかかる。もし、この途中で「libtinfo.soが見つからない」と怒られたら、libncursesを入れることで解決する可能性がある。僕の場合は
sudo yum install ncurses-devel
としてから、再度stack install
したらいけた。
formura
は、$HOME/.local/bin
にインストールされるので、パスを通しておこう。
export PATH=$PATH:$HOME/.local/bin
パスが通ったか確認してみよう。
$ formura
Usage: formura FILES... [-o|--output-filename FILENAME] [--nc FILENAME]
[-v|--verbose] [--ncopt ARG] [-f|--flag ARG] [--sleep SECOND]
generate c program from formura program.
上記のようなメッセージが表示されたら正しくインストールされている。
Formura言語の記述
Formuraは、数値計算、特に規則格子計算を記述する言語だ。その言語仕様は公式リポジトリの「Download Formura Language Specification (pdf)」で参照できる。とりあえず必要なファイルは*.yaml
ファイルと*.fmr
ファイルだ。
YAMLファイルには、格子の情報を記述する。とりあえず格子間隔1、格子点64点の一次元系を定義しよう。後でGray-Scottのシミュレーションをする予定なので、gs.yaml
というファイル名にしておく。
length_per_node: [64.0]
grid_per_node: [64]
length_per_node
が1ノードが担当する領域の長さ、grid_per_node
が、1ノードが担当する領域のグリッド数だ。今回は1次元なのでそれぞれ要素数1のリストとして与えている。
さて、次にgs.fmr
にFormura言語を記述する。拡張子はfmr
とする。
dimension :: 1
axes :: x
begin function u = init()
double [] :: u = 0
end function
begin function u2 = step(u)
u2 = u
end function
外見や、ベクトル、行列の扱いについてはFortran90ライクに見える。
最低限必要なのは
- 次元の宣言
- 軸の宣言
- 初期化関数
init
- 時間発展関数
step
の4種類だ。内容については次回説明するが、とりあえず
-
u
という一次元配列を用意して0で初期化する関数init
-
u
を受け取って、それをそのまま次のステップの値u2
とする(つまり何もしない)時間発展関数step
を記述している。
YAMLとfmrファイルを作成したら、formura
に食わせる。
$ formura gs.fmr
Generating code...
Generate:
gs.c
gs.h
run
ソースコードであえるgs.c
やgs.h
、実行スクリプトrun
を吐く。
これを実行するためのmain
関数を書こう。FormuraはC言語を吐くが、趣味でC++で書く。
#include "gs.h"
int main(int argc, char **argv) {
Formura_Navi n;
Formura_Init(&argc, &argv, &n);
Formura_Finalize();
}
先程作成されたgs.h
をインクルードした上で、Formura_Init
で初期化、Formura_Finalize
で終了する。MPIと似たインタフェースだ。
これをコンパイルする。
$ g++ main.cpp gs.c
C++とCのソースを混ぜてコンパイルしているので、たとえばclang++を使うと文句を言われるが、とりあえず気にしないことにする。
できたバイナリa.out
を実行してみる。
$ ./a.out
エラーなく実行できれば成功である。何もしないプログラムなので、何も表示されない。
まとめ
格子計算プログラム生成言語Formuraをインストールし、使ってみた。まだインストールとコンパイルをしてみただけだが、次回以降、簡単なシミュレーションをしてみる予定である。
その2へ続く。