-
-
Save takagi/3e4f3a8678a8f74e852e to your computer and use it in GitHub Desktop.
https://github.com/takagi/cl-cuda/tree/issue/49.symbol-macro | |
・時間を食う処理は、update-density と update-force で、全体の 90% 以上 | |
・アルゴリズムは所与としたとき、GPU の使い方のレベルで高速化する余地はあるか? | |
→メモリアクセスにあまり局所性がなさそう | |
→グローバルメモリへのアクセスが律速なので、それ以上はもうやりようがない? | |
・グリッドやブロックの割当てはどのようにやるもの? | |
→影響するパラメータを変えるたびに手計算してハードコードしているがそういうもの? | |
・粒子インデックスの計算はどのようにやるもの? | |
→グリッドやブロックの割当て方に影響を受けるがそういうもの? | |
→[0,n) でディスパッチしてくれたらいいのに |
pressure-term
と visconsity-term
の rho
は i
でアクセスしており2回のロードが行われます。
update-force
でロードして各関数に渡すようにした方が良いです。
(デバイスメモリがキャッシュされるアーキテクチャだと速度差はないかも)
defglobal
は毎回ロードが発生しますが、constant
にするとキャッシュが効くので構文を追加した方が良いです。
(デバイスメモリがキャッシュされるアーキテクチャだと速度差はないかも)
浮動小数点の即値が無印でdoubleのまま出ており、Common Lisp側でsingle floatを指定したら、出力側の即値にfが付くように構文を変更した方が良いです。
現状 with-particle-index
が1スレッド1インデックスとなっているため全てのデバイスメモリをランダムアクセスするが、neighbor-map
へのアクセスはリニアなので、with-particle-index
を1ブロック1インデックスとし neighbor-map
のアクセスをコアレスにし結果をリダクション加算すると、
加算順序の入れ替えによる誤差は出るものの高速化する可能性があります。
(これ本当のところどうなるかやってみないとよく分からない)
これに加えて、さらに1ブロックnインデックスの処理を行うようにし、各ループの計算結果を共有メモリ保持して置き、一定量たまったら書き出すとコアレスアクセスになって速いです。
両方の対応をすると一つのカーネルの中で、各スレッドが l
を基準に動く時と i
を基準にで動く時が出てきて大分混乱はします。
update-density
で norm
計算をし poly6-kernel
でも norm
計算をしていますが、これは再計算している可能性があるので変数に入れて再利用した方が速いです。
defglobal は毎回ロードが発生しますが、constant にするとキャッシュが効くので構文を追加した方が良いです。
(デバイスメモリがキャッシュされるアーキテクチャだと速度差はないかも)
浮動小数点の即値が無印でdoubleのまま出ており、Common Lisp側でsingle floatを指定したら、出力側の即値にfが付くように構文を変更した方が良いです。
用語的に
グリッドやブロック
ではなく、ブロックやスレッド
ですかね。(blockDimがスレッドの数でなんか分かりずらいですが。。。)アルゴリズムや対象のGPUによってブロックやスレッドの役割とか次元をどうするかは変わりますし、数値は実測してハードコードします。
最内ループの演算を微妙に変えた結果、使用するレジスタ数が変わってオキュパンシーが変化することにより、blockDimを変更することもあります。
要素数がgridDim, blockDimで指定できる範囲内ならば、基本はsphのコードのようにしていて、割り当て方の影響を受けます。
チューニングの結果としてblockDimが固定値になることが多いので、呼び出し側で
gridDim = (n / blockDim) + ((n % blockDim == 0) ? 0 + 1)
みたいなことをやったりする。OpenCLではそんなIFになりましたね。。。