OpenMP変数編

まぁー
http://codezine.jp/article/detail/5290
ここを見て、酷いサンプルだなーと思ったんだけど・・・
ange1さんの
http://d.hatena.ne.jp/ange1/20100723/1279903236
これを見て、思っていた以上に酷かったことがわかったw


#pragma for


これなんか、「ompを省略できるのかーでもVS2005じゃエラーになるなぁ」とか思ってたw
lastprivateって、本当はどんな使い方するのか?ってほうに興味が行ってたんですが・・・
lastprivateでどうやって初期値設定するのか、わからなかったし、結果を受け取ってどうするのかも思いつかなかった。
これまた、ange1さんが紹介していた仕様書でスッキリした。
そうか、ループに使ってる変数を指定すれば意味がでるんですねぇ。

int i;
char tmp[11];
#pragma omp parallel for lastprivate(i)
for (i=0;i<10;i++)
{
    tmp[i]='w';
}
tmp[i]='\0';

こんな感じですかねぇ、コンパイル環境がないので動作確認してませんが(^^;
わかってしまえば、よくあるコードを実現するだけのものだったわけですねぇ。
元記事では、変数もイロイロ説明されていたんですが・・・
わかってから見ると、簡単なものを複雑に説明されているような感じでした。


結局のところー同じ名前で同じ型の別変数をスレッド数分、生み出しているだけだったんですねぇ>private
だから、なにもしなければ初期化されていないだけと・・・
んでもって、元の変数の値を初期値として使うのが、firstprivate。
その逆で、使い終わったら、元の変数の値を書き換えるのがlastprivate。
そして、特になにも指定しなかった変数はsharedとして扱われるわけですね。
例外で#pragma omp parallel forで指定されたループ変数はprivateになるっと。

競合をなくす簡単な方法なんでしょうねぇ>private
同じ名前なのは、OpenMPが使えない環境での互換性を保てるからってことかな。
上のlastprivateサンプルを考えてみて、その辺の利点がわかったような気がする。
よくできてるよなぁ。


そうそう、競合で思い出した。
ange1さんの指摘している、sharedサンプルのバグ。
てっきり排他処理されているものだと思っていたら、実は違ったんですねぇ。
実際に、元記事のループを10から1000に変えてみたら見事にバグりましたw
ループで使っているiも共有されてしまうから、結構カオスな感じかなぁ。
lastprivateに気をとられて気が付かなかったけど、#pragma forが使われているサンプルは全滅ですな。
よくみると、結果の数値がおかしかったんですねぇ。
sharedサンプルの場合、0〜9の合計なんだから並列に計算したって答えは45にならないといけないわけで・・・
90になっているのがおかしいんですよねぇ・・・まぁ、これ偶然の結果なんですが・・・
lastprivateサンプルの場合は、プライベートなんだから、45よりも小さくなるはず・・・ですよね。
reductionのサンプルもバグが判りやすいですね、合計が450になってるから(^^;
これ、450になってるのも偶然なんですよねぇ、iが共有されているから数を増やすとさらにバグるw


結果を見れば、「並列処理特有のバグ」をほとんどのサンプルに持ち込んでいる悲しい記事だったと・・・
おかしな結果が綺麗な数字になっていたために、見逃してしまったんでしょうねぇ。