この記事では: http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484?pgno=2は、 (where: )volatile
などの の
最適化を行うことはできないと述べています。volatile int& v = *(address);
v = 1; // C: write to v
local = v; // D: read from v
これに最適化することはできません:
v = 1; // C: write to v
local = 1; // D: read from v // but it can be done for std::atomic<>
1行目と2行目の間でv
値がハードウェアデバイスによって変更される可能性があるため、実行できません(キャッシュコヒーレンスが機能しないCPUではありません:ネットワークアダプター、GPU、FPGAなど...)(sequentila/concurrency)、これは、このメモリ ロケーションにマップされます。v
ただし、CPU キャッシュ L1/2/3 にキャッシュできない場合にのみ意味があります。これはvolatile
、1 行目と 2 行目の間の通常の (非) 変数では時間が短すぎて、キャッシュがトリガーされる可能性があるためです。
volatile
修飾子は、このメモリ位置のキャッシュがないことを保証しますか?
答え:
- いいえ、このメモリ ロケーション
volatile
がキャッシュされないことを保証するものではありません。また、C/C++ 標準またはコンパイラ マニュアルには、これに関する記述はありません。 - デバイス メモリから CPU メモリにマップされたメモリが既にWB ではなく WC (書き込み結合)としてマークされている場合、メモリ マップ領域を使用すると、キャッシュがキャンセルされます。また、 cache-flushing を実行する必要はありません。
- 反対に、CPU メモリがデバイス メモリにマップされている場合、偶然にも、CPU のクリスタル上にあるコントローラー PCIE が、このデバイスから DMA を通過するデータをスヌーピングし、CPU キャッシュ L3 を更新 (無効化) します。この場合、を使用するデバイス上の実行可能コード
volatile
が同じ 2 つの行を実行しようとすると、デバイスのキャッシュ メモリ (キャッシュ GPU-L2 など) もキャンセルされます。また、GPU-cache-flushing を実行する必要はなく、 CPU-cache-flushing を実行する必要もありません。std::atomic_thread_fence(std::memory_order_seq_cst);
また、 PCIE を介した DMA との L3 キャッシュ (LLC) コヒーレンシが必要な場合は、CPU を使用する必要があるかもしれませんが、L1/L2 は必要ありません。nVidia CUDA の場合、以下を使用できます。void __threadfence_system();
- アライメントされていないデータを送信するときは、DMA-controllers-cache をフラッシュする必要があります: ( WDK :
KeFlushIoBuffers(), FlushAdapterBuffers()
) - また、MTRR レジスタを使用して、任意のメモリ領域をキャッシュされていない WC マークとしてマークすることもできます。