VisualC++2010におけるOpenMPの呪い

OpenMPを使用しているプログラムをソースを変更せずにVS2008からVS2010に移行したとき、VS2008でそれほどCPUロードがあがらなかったものなのにCPUロードが100%近くになってしまうという挙動の変更があったようだ。非常に面倒なことをしてくれた。
ちょうどこの問題に遭遇したので検索してみるとすでに有名な問題となっていたようだ。
http://social.msdn.microsoft.com/Forums/en-US/parallelcppnative/thread/528479c8-fb70-4b05-83ce-7a552fd49895/
forやsectionsディレクティブを指定したときにOpenMPライブラリが暗黙的に実行するスピンウェイトが問題となっているようだ。 おそらくディレクティブの指定などで回避可能なのかもしれないが・・・ しょうもない。
IntelC++にはこの挙動を簡単に制御できるOpenMP用のメソッドが用意されているのだがVSにはない・・・ なんということをしてくれたのだMSよ


で、ちょこっと調べる・・・大体解決。
forやsectionsディレクティブの条項に「nowait」をつける。これで暗黙のスピンウェイトがなくなりParallelBarrierNなんちゃらという関数が大量に呼ばれることがなくなるようだ。それとともにCPUロードが100%近くまで上昇することもなくなることを確認。ヤレヤレ これによって問題などが発生しないかどうかわかりかねる部分も多いが今のところリソース競合的な挙動を見せていないので様子見。
関数としてはないがディレクティブの条項(オプション的なものとかんがえていい)として存在したというオチ。


それにしてもこの実装の仕方は非常に問題である。forやsectionsといったOpenMPによる並列化ブロックをコンストラクトするためのディレクティブは、導入のドキュメントなどでnowaitを指定しろなどと書かれていない場合が多い。 これを素直に使ってとりあえずはまるのは目に見えているのだが・・・・・