2009年11月1日日曜日

Haskell、OCamlでSPH法


このエントリに載せていたC++のコードを、HaskellとOCamlで書いてみました。(あと、C++のコードも整理しました)

コードを置いておきます。
Haskell版(sph.hs)の実行方法は、

$ ghc --make -O sph.hs
$ ./sph 300

です。./sphの引数は計算するステップ数です。上記のsph.zipにはData/Vector.hsというベクトル演算のためのモジュールを入れてあります。

同様に、OCaml版(sph.ml)の実行方法は、

$ ocamlopt -pp 'camlp4o -parser Camlp4ListComprehension' -o sph sph.ml
$ ./sph 300

です。-ppオプションは、プリプロセッサにCamlp4を使ってOCamlでリスト内包表記を使えるようにするためのものです。

もう1つC++版(sph.cpp)の実行方法は、

$ g++ -O2 -o sph sph.cpp
$ ./sph 300

です。以前はboostを使ってみていたのですが、boostを用意する手間やコンパイルの遅さを考えるとあまり意味がないので、使わないようにしました。(あと、このコードを書く前にSTLの総称プログラミングのスタイルでも書いてみたのですが、かえってわかりづらくなったのでやめました)

この3つの実行時間ですが、

▼C++
$ time ./sph 30
real 0m6.367s
user 0m4.916s
sys 0m0.157s

▼OCaml
$ time ./sph 30
real 0m11.718s
user 0m9.461s
sys 0m0.241s
→ cppの約2倍

▼Haskell
$ time ./sph 30
real 1m23.961s
user 1m2.786s
sys 0m2.169s
→ cppの約15倍

On PowerBook G4 1.5GHz (Mac OSX 10.4.11)

のようになりました。

OCamlがC++の約2倍、HaskellがC++の約15倍です。

Haskellがあまりに遅いのでOCamlで書いてみたというのがあるのですが、それにしても遅い。ここまで遅いものなのだろうか?

2009/11/5追記:計りなおすと、Haskell版はC++版の約5倍ですんでました…

それに対して、OCamlは本当に速いですね。いまのコード(sph.ml)は粒子を非破壊的に更新しているのですが、それでもC++の約2倍で実行できています。

次は、Haskell版とOCaml版で使っている遅延ストリームについて書きます。


■流体シミュレーションに関するエントリ
粒子法のプログラム第1回(概要)
粒子法のプログラム第2回(プログラムの大枠)
粒子法のプログラム第3回(データ構造)
粒子法のプログラム第4回(密度と圧力の計算)
粒子法のプログラム第5回(力の計算)
粒子法のプログラム第6回(境界条件と粒子位置の更新)
粒子法のプログラム最終回(粒子の出力)
【粒子法】粒子を流体としてレンダリング
3次元の粒子法シミュレーション
粒子法のシーンを2倍のサイズにしてみたが…
粒子法のシーンを2倍のサイズにしてみた
SPHによる巻き波のシミュレーション2
Haskell、OCamlでSPH法
このあとやりたいこと
カメラ位置を変えて流体をレンダリング
固液連成シミュレーション

■剛体シミュレーションに関するエントリ
粒子ベース剛体シミュレーション(プレビュー)
粒子ベース多体衝突シミュレーション
引き続き、粒子ベース剛体シミュレーション


粒子法(SPH)のプログラム
粒子法(SPH)のプログラムを解説したシリーズです。ソースコードも公開しています。

粒子法(SPH)のプログラム一覧



動画
シミュレーションの結果をレンダリングして作った動画です。流体シミュレーションや剛体シミュレーションの動画を見ることができます。

動画の一覧



-

3 件のコメント:

匿名 さんのコメント...

プログラム読ませていただきました。パラメタの調節が上手くいかず苦戦していたのでとても助かりました。C++版のコードでneighbor_map_Idxの定義のなかでmxの定義にMIN.yを使っていますがここは多分MIN.xだと思います。

kamonama さんのコメント...

コメントありがとうございます!

neighbor_map_idxのMIN.yは、そのとおりタイポでした。ご指摘ありがとうございます。

パラメータ周りでお役に立てたようで、嬉しいです。

oruka さんのコメント...

sph.cppコードを読ませていただきました。
右端が空白になっている、6つの#includeがありました。この6つの空白、何をいれればよいのでしょうか?もしよろしければお教えください。