変数idを__shared__にすると思い通りに動くよ!
い み が 。
変数idを__shared__にすると思い通りに動くよ!
い み が 。
アレな状況に陥ったので報告。本家forumで議論してきたほうがいいかもシレン。
grid(2,1,1)な実行後のvalueは何になるか。
答えは
value[0] = 0
value[1] = 0
……いや、それはおかしいだろう。
実は、例えば以下のように書くと想定どおりの答えが得られる。
これで答えは
value[0] = 1
value[1] = 2
となる。
でもいいや。
なんてのもありらしい。
あくまで予想なんだけど、ifブロックの中で変数idが使われていないという理由で、コンパイラがid変数を最適化の課程で殺しているんじゃないだろうか。だとしたらコンパイラのバグだよなぁ……。
やっぱ本家にゴルァかな?勘違いかもしれないので一日熟成させよう。
このへんの続き。
前回は何故か__syncthreads()を使ったりと妙にキモイことをやっていたので、追実験。
atomic関数の存在も念頭に置いてみる。
まぁこんなケースを考えることにする。
んで同期をどうやるか。
とりあえず考えたのが以下の実装。
atomicAddで加算の保証が出来るので、あとは全blockが加算するのを待てばいいんじゃないかと。
うん。失敗した。無限ループっぽい。
直感的にはこれで行けそうなんだけど、何かひっかかるらしい。
という感じに__syncthreads();を入れると正しく動作する。
__syncthread()にそれらしい仕様はない気がするんだが……?
ところで、atomicAddは確実に読み出して加算ができる、ってのはいいんだけど、その処理の途中で別のblock/threadが値を読んでしまうことってあるんだろうか。いや、別に「0が読めるか1が読めるかわからないよ」ってのは構わないというか当然なんだけど、何故か全然違う値が読めたりすると危険だよなぁ……。
さて、胡散臭い__syncthreads()を使わずにちゃんとやるにはどうすればいいかなんだが、作業用の変数を追加して
とやったらうまくいった。
安全を確保するならwaitflagの変更はatomicの方がいいのかもしれないけど、まぁ大丈夫だろう。
さて。以上の振る舞いから、今回のglobal memory spaceの変数の参照はコンパイラによって最適化されてしまっているのではないかという仮説が立てられる。
nvccの-ptxや-keepで中間コードが覗けるんだけど、これ見て判断するのはちょっとツライんだよなぁ。
最後。
仮設を踏まえて適当にうまく行く記述を考えてみた。
明示的にglobal memory spaceからの再読み込みを行うような感じ。
実際、これで思い通りの動作は出来ている。
ちなみに、どの実装にしても複数回の実行にはちょっとだけ工夫が必要かもしれない。
作業用変数のクリアが必要だから。
とはいえ、作業用変数を多重化して、同期が終了するときに今使ったものとは別の作業用変数を初期化してやれば動きそうだから多分大丈夫だろう。たぶん。
以下、#ifで切ったプログラム全体。長いけど参考にベタッと貼っておく。
うまくいってなかったのが解決したかもしれないのでメモ。
っつーかptetex -- teTeX 用日本語パッチ集に従っただけ。
makeにこけたけど、flexとyaccとlibXaw-develとncurses-develあたりを追加してインストール完了。
platexとdvipdfmxでPDFの生成までは確認。
(……あれ?dvipdfmxっていつ入れたんだっけ……?)
何か気がついたことがあったらまた書く。