C
C++
Haskell
Formura

格子計算プログラム生成言語Formuraを使ってみる その1


はじめに

プログラマは計算機に対して、「別に凝ったをやれとは言わないが、自明なことはやってくれよ」と思うものだ。例えば規則格子における差分法、特に陽解法は、式と差分方式さえ決まれば、(最適化とか考えなければ)後は自明なコーディングになる。さらに、領域分割による分散メモリ並列を考えた時、(効率とか考えなければ)やはり自明なだけで面倒なコーディングをする必要がある。

こういう「自明かつ面倒なコーディング」をやらなければいけなくなった時、「自動化したい」と思うのは自然な発想だ。Formuraは、まさにそのような思想で作られた、格子計算プログラム生成言語(というかフレームワーク)である。

本稿では、このFormuraを使ってみる。



  • その1 インストールとコンパイルまで ←イマココ


  • その2 一次元熱伝導方程式


  • その3 二次元熱伝導方程式


  • その4 反応拡散方程式(Gray-Scott系)


インストール

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というファイル名にしておく。


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とする。


gs.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.cgs.h、実行スクリプトrunを吐く。

これを実行するためのmain関数を書こう。FormuraはC言語を吐くが、趣味でC++で書く。


main.cpp

#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へ続く。


参考