高速並列演算多次元多相配列repaを使ってみる。

Haskellのライブラリで前から気になっていたrepaを触ってみます。高速並列演算多次元多相配列ですからね。それは気になります。regular pallalelの「regular」の意味がいまいち分かりませんが。
丁度@shelarcyさん記事が書かれたことをきっかけとしています。

ここではrepaでライフゲーム作ってみます。
ライフゲームは周囲8マスの影響で次の時刻の生死がわかるという仕組みを持っています。要するに流体のシミュレーションと同じ仕組みを持っているんですね。ライフゲーム書ければ流体のシミュレーションが書けるわけですよ多分。


ソースは一番下においておきますのでポイントだけ。
Arrayからライフゲーム的に次の時刻のArrayを得るためにはtraverseを使えばいいらしい、という情報を得たのでそれを使います。
残念ながら上記@shelarcyさんの記事ではtraverseはまだ説明されていませんでした。今後解説されるのでしょうか。
ということである時刻の配列(ここではBoard U)から次の時刻の配列(ここではBoard D)を得るには以下の様に書けます。

step :: BoardSize -> Board U -> Board D
step siz board = R.traverse board id nextStatus

これだけです。まあnextStatusが多少複雑ですが。素敵ですね。
そしてそのstepでの返り値、Delayed Array(Board D)をcomputePで処理して次の時刻の値を取得します。
repeatStepはそれを適当に(本当に適当に...)表示しているだけです。

repeatStep :: BoardSize -> Board U -> IO ()
repeatStep siz board = do
    board' <- R.computeP $ step siz board  
    usleep 120000
    putStr "\x1b[2J"
    putStr "\x1b[1;1H"
    printListToRect siz $ R.toList board'
    repeatStep siz board'

このcomputePだけで並列処理が出来ます。素敵ですね。
Delayed arrayが返ってくるのに逐次computePするのは少々もったいない気分ですね。まあ今回は仕方ない。

コンパイルして実行します。色々付けるらしいです。

$ ghc -Odph -fllvm -optlo-O3 -rtsopts -threaded lifegame.hs
$ ./lifegame +RTS -N2 

GPUもちょっと触ってみたくなりますね。


ということでソースです。