c++ - volatile 限定符是否取消了此内存的缓存?

标签 c++ c caching c++11 concurrency

在本文中:http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484?pgno=2 说,我们不能对 volatile 做任何优化,即使是 (where: 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, etc...) (sequentila/concurrency), 映射到这个内存位置。但只有当 v 不能缓存在 CPU 缓存 L1/2/3 中时才有意义,因为对于通常的(非 volatile)变量,介于 1st 和 2nd 之间行太小的时候很可能触发缓存。

volatile 限定符是否保证不对该内存位置进行缓存?

回答:

  1. 不,volatile 不保证不缓存此内存位置,并且在 C/C++ 标准或 compiler manual 中没有任何相关内容.
  2. 使用内存映射区域, when memory mapped from device memory to CPU-memory is already marked as WC (写入组合)而不是 WB,取消缓存。 并且不需要进行缓存刷新
  3. 相反,如果 CPU 内存映射到设备内存,那么顺便说一句,位于 CPU 晶体上的 Controller PCIE 正在监听从该设备通过 DMA 的数据,并更新(无效)CPU 缓存 L3 .在这种情况下,如果设备上的可执行代码使用 volatile 尝试执行相同的两行,它也会取消设备的缓存内存(例如在缓存中GPU-L2)。和 need not to do GPU-cache-flushing and need not to do CPU-cache-flushing 。同样对于 CPU 可能需要使用 std::atomic_thread_fence(std::memory_order_seq_cst); if L3-cache(LLC) coherency with DMA over PCIE, but L1/L2 is not .对于 nVidia CUDA,我们可以使用:void __threadfence_system();
  4. 发送未对齐的数据时,我们需要刷新 DMA Controller 缓存:(WDK: KeFlushIoBuffers(), FlushAdapterBuffers())
  5. 此外,我们可以通过 MTRR 寄存器将任何内存区域标记为未缓存的 WC 标记。

最佳答案

volatile 确保变量不会被“缓存”在 CPU 寄存器中。 CPU 缓存对程序员是透明的,如果另一个 CPU 写入另一个 CPU 缓存映射的内存,第二个 CPU 的缓存将失效,因此它将在下一次访问时再次从内存中重新加载值。

关于 Cache coherence 的事情

至于外部内存写入(通过 DMA 或其他独立于 CPU 的 channel ),您可能需要手动刷新缓存(参见 this SO 问题)


C 标准 §6.7.3 7:

What constitutes an access to an object that has volatile-qualified type is implementation-defined.

关于c++ - volatile 限定符是否取消了此内存的缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18550784/

相关文章:

python - 获取网页的当前版本

c++ - 无法创建二维数组

c++ - "typename"和 "template"关键字 : are they really necessary?

c++ - 如何从 C++ 中的现有模板函数定义新函数

c++ - OpenGL 示例中 WinMain 错误的重新定义

performance - 缓存和 HTTP/2

c++ - 元组没有按顺序构建?

c - 数的 n 次根

c - 为什么在将 malloc 与结构值一起使用时出现 -Wsign-conversion 编译器警告?

java - JCS 的示例