c++ - 如果我在 _mm_clflushopt() 之后不发出 _mm_sfence() 会发生什么(不好的)事情?

标签 c++ concurrency x86-64 cpu-cache memory-fences

在释放内存之前,我要从 CPU 缓存中逐出内存范围。理想情况下,我只想放弃这些缓存行而不将它们保存到内存中。因为没有人会使用这些值,无论谁再次获得该内存范围(在 malloc()/new/_mm_malloc() 等之后)。 ) 将首先用新值填充内存。作为this question suggests ,目前似乎没有办法在x86_64上实现理想。

因此我正在执行 _mm_clflushopt()。据我了解,在 _mm_clflushopt() 之后,我需要调用 _mm_sfence() 以使其非临时存储对其他内核/处理器可见。但在这种特定情况下,我不需要它的商店。

所以如果我不调用 _mm_sfence(),会不会有什么不好的事情发生?例如。如果其他一些核心/处理器设法足够快地再次分配该内存范围,并开始用新数据填充它,是否会发生新数据被当前核心刷新的旧缓存同时覆盖的情况?

编辑:快速后续分配不太可能,我只是描述这种情况,因为我也需要程序在那里是正确的。

最佳答案

clflushopt 对于这个用例来说是个糟糕的主意。在覆盖它们之前从缓存中逐出行与您想要的相反。如果它们在高速缓存中很热,您可以避免 RFO(读取所有权)。

如果您使用的是 NT 商店,它们会驱逐所有仍然很热的线路,因此不值得花费周期先执行 clflushopt

如果不是,您通过保证最坏的情况完全搬起石头砸自己的脚。参见Enhanced REP MOVSB for memcpy有关写入内存以及 RFO 与无 RFO 存储的更多信息。 (例如,rep movsb 至少可以在 Intel 上执行无 RFO 存储,但仍将数据保留在高速缓存中。)请记住,L3 命中可以比进入 DRAM 更快地满足 RFO。

如果您要编写一个带有常规存储的缓冲区(这将是 RFO),您可以在准备好实际写入之前对其进行 prefetchw 以使其在 L1D 中进入独占状态.

clwb(Cache-Line Write Back (without evicting))可能在这里很有用,但我认为 prefetchw 至少总是和它一样好,如果不是更好的话(特别是在 AMD 上,MOESI cache coherency 可以在缓存之间传输脏行,因此您可以将仍然脏的行放入 L1D,并且能够替换该数据而无需将旧数据发送到 DRAM。)

理想情况下,malloc 将为您提供当前内核的 L1D 缓存中仍然热的内存。如果你发现很多时候,你得到的缓冲区仍然是脏的,并且在另一个核心上的 L1D 或 L2 中,然后查看带有每个线程池或某种类似 NUMA 的 malloc线程感知。

As I understood, after _mm_clflushopt() I need to call _mm_sfence() to make its non-temporal stores visible to other cores/processors.

不,不要将clflushopt 视为一家商店。它不会使任何新数据全局可见,因此它不会与内存操作的全局顺序交互。

sfence您的线程的后续存储等待,直到刷新的数据一直刷新到 DRAM 或内存映射的非 volatile 存储。

如果您要刷新由常规 DRAM 支持的行,您只需要在存储前使用 sfence 即可启动非相干 DMA 操作,该操作将读取 DRAM 内容而不检查缓存。由于其他 CPU 内核确实总是通过缓存,因此 sfence 对您没有用处或不必要。 (即使 clflushopt 一开始是个好主意。)


即使您谈论的是实际的 NT 商店,其他核心最终也会在没有 sfence 的情况下看到您的商店。如果您需要确保他们在看到您的 NT 商店之前他们看到一些后来的商店,您只需要sfence。我在 Make previous memory stores visible to subsequent memory loads 中对此进行了解释

can something bad happen?

不,clflushopt 不会影响缓存一致性。它只是触发回写(和驱逐),而不会让以后的存储/加载等待它。

您可以clflushopt 分配内存并由另一个线程使用,而不会影响正确性。

关于c++ - 如果我在 _mm_clflushopt() 之后不发出 _mm_sfence() 会发生什么(不好的)事情?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46004527/

相关文章:

java - 这是在 Java 中创建锁的可接受方式吗?

协程 : Where to close

optimization - GCC 不使用 inc

c++ - 从低到高的隐式转换

C++11,std::atomic 在 clang 3.2 和 libc++ 中损坏了吗?

c++ - 二维阵列反转线中的段错误

java - 从另一个 Jframe 打开后 JPanel 内容变黑

c++ - Taglib 设置相册图片但给出 seg 错误

linux - 调试:我在反汇编的调用者中没有看到回调作为 callq 或内联 asm (Linux x86_64)

assembly - NASM x86_64 printf 第 7 个参数