ゆき社長

シーゲンガーのお勉強 ゲームプログラマ、ゲーマー、色々!

volatileによる最適化阻止と、局所的な最適化阻止

Qiitaにまとめたけど

http://qiita.com/YukiMiyatake/items/1191ab03b6c0b5a22876

マルチスレッドや割り込みで変更される可能性のあるフラグを

コンパイラは最適化し、フラグを無効にしてしまう

ってのは Cゲンガーは知ってると思う

それを防止するのは volatile ってのも知ってると思う

そして マルチスレッドの場合は、volatileだけじゃダメで

CPUキャッシュやらIOデバイスコントローラのキャッシュやらがちゃんと write backしなきゃダメ

なので mutex あるいは速度が必要な時は atomic 操作しなければならない

ってのも 暗黒Cゲンガーなら知ってると思う

で 本題は volatileは 変数とメンバ関数にしか付けれないのね。

C言語だと変数にしか付けれないので、volatileを使うと

その変数が関わる部分全てが 最適化阻止されてしまう!!

それって 微妙に悔しいじゃん! 最適化して欲しくない箇所のみ ピンポイントで阻止したい。

C++だと、メンバ変数にはvolatile指定できるので

フラグの getterを volatile有りと無しで2個作って 必要に応じて呼び分ければ良いんだけど

グローバル関数や、 関数オブジェクトには volatile指定出来ないんですよ!!

この、関数オブジェクトにvolatileできないってのは 致命的ですね

(一応 提案として ラムダにvolatile指定出来るようにするというのが 着てるので近い将来 可能になるはず)

で、グローバル関数で通用する、部分的に最適化を阻止する方法を見つければ

C言語だろうと 関数オブジェクトだろうと問題ないので

色んな方法で考えてみた。

結果を言うと

1、最適化して欲しくない場所は、(インライン)アセンブラで書く

2、volatileポインタへのキャストを行う

って事で インラインアセンブラは、プロセッサ依存とか、アドレスモードとか色々問題が出るので

結論から言うと volatileポインタにキャストして使うのが良い。

また 逆に 変数を volatile宣言し、 const_castで volatileを外す事で、逆の動作

デフォルト最適化阻止、局所的に最適化ON

ってことも出来るけど

使用頻度としては滅多にないよね。

とりあえず 調査した!