13

この記事では: 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修飾子は、このメモリ位置のキャッシュがないことを保証しますか?

答え:

  1. いいえ、このメモリ ロケーションvolatile がキャッシュされないことを保証するものではありません。また、C/C++ 標準またはコンパイラ マニュアルには、これに関する記述はありません。
  2. デバイス メモリから CPU メモリにマップされたメモリが既にWB ではなく WC (書き込み結合)としてマークされている場合、メモリ マップ領域を使用すると、キャッシュがキャンセルされます。また、 cache-flushing を実行する必要はありません
  3. 反対に、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();
  4. アライメントされていないデータを送信するときは、DMA-controllers-cache をフラッシュする必要があります: ( WDK : KeFlushIoBuffers(), FlushAdapterBuffers())
  5. また、MTRR レジスタを使用して、任意のメモリ領域をキャッシュされていない WC マークとしてマークすることもできます。
4

2 に答える 2

8

volatile変数が CPU レジスタに「キャッシュ」されないようにします。CPU キャッシュはプログラマーに対して透過的であり、別の CPU のキャッシュによってマップされたメモリに別の CPU が書き込むと、2 番目の CPU のキャッシュが無効になるため、次のアクセス中にメモリから値が再度リロードされます。

キャッシュの一貫性について

外部メモリの書き込み (DMA または別の CPU に依存しないチャネル経由) については、キャッシュを手動でフラッシュする必要がある場合があります (このSO の質問を参照)


C 標準 §6.7.3 7:

volatile 修飾された型を持つオブジェクトへのアクセスを構成するものは、実装によって定義されます。

于 2013-08-31T17:21:39.003 に答える