より明確に言えば(うまくいけば)、
mem_fence()
mem_fence() の前に作業アイテムの呼び出しによって行われたローカルおよび/またはグローバルメモリへのすべての読み取り/書き込みが、作業グループ内のすべてのスレッドに表示されるまで待機します。
それは次のとおりです。http://developer.download.nvidia.com/presentations/2009/SIGGRAPH/asia/3_OpenCL_Programming.pdf
メモリ操作は、実行中のデバイスに合わせて並べ替えることができます。仕様では、(基本的に) メモリ操作の並べ替えは、メモリが単一の作業項目内で一貫した状態にあることを保証する必要があると述べています。ただし、(たとえば) ストア操作を実行し、ローカル/グローバル メモリへの書き込みに適した時期が来るまで、値を作業項目固有のキャッシュに保存することを決定した場合はどうなるでしょうか。そのメモリからロードしようとしても、値を書き込んだワークアイテムのキャッシュにあるので問題ありません。しかし、work-group 内の他の work-item はそうではないため、間違った値を読み取る可能性があります。メモリ フェンスを配置すると、メモリ フェンスの呼び出し時に、ローカル/グローバル メモリ (パラメーターに従って) の一貫性が確保されます (すべてのキャッシュがフラッシュされ、
まだ紛らわしいことは認めますし、私の理解が 100% 正しいと断言するつもりもありませんが、少なくとも一般的な考え方だと思います。
ファローアップ:
CUDA メモリ フェンスについて説明しているこのリンクを見つけましたが、OpenCL にも同じ一般的な考え方が適用されます。
http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/NVIDIA_CUDA_Programming_Guide_2.3.pdf
セクションB.5 メモリ フェンス関数を参照してください。
1 回の呼び出しで数値の配列の合計を計算するコード例があります。コードは、各ワークグループで部分合計を計算するように設定されています。次に、実行する合計がさらにある場合、コードは最後の作業グループに作業を行わせます。
したがって、基本的に各ワークグループで 2 つのことが行われます。グローバル変数を更新する部分合計と、カウンタ グローバル変数のアトミック インクリメントです。
その後、さらに作業が残っている場合は、カウンターを ("work-group size" - 1) の値までインクリメントしたワークグループが最後のワークグループと見なされます。そのワークグループは仕上げに進みます。
さて、問題は(彼らが説明しているように)、メモリの並べ替えやキャッシュのために、カウンターがインクリメントされ、最後のワークグループがその部分合計グローバル変数がその作業を開始する前に作業を開始する可能性があることですグローバルメモリに書き込まれた最新の値。
メモリフェンスは、フェンスを通過する前に、その部分合計変数の値がすべてのスレッドで一貫していることを保証します。
これが意味をなすことを願っています。それは紛らわしい。