【问题标题】:What (bad) can happen if I don't issue _mm_sfence() after _mm_clflushopt()?如果我在 _mm_clflushopt() 之后不发出 _mm_sfence() 会发生什么(坏的)?
【发布时间】:2018-02-10 18:31:36
【问题描述】:

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

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

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

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

【问题讨论】:

  • 请问,首先驱逐缓存的目的是什么?
  • @PasserBy,让它尽快被接下来真正使用的数据占用。在不明确驱逐它的情况下,CPU 会将旧的(不再使用的)数据保留在缓存中,直到旧数据变为最近最少使用 (LRU) w.r.t。缓存中的其他数据。
  • 如果可以证明缓存中的内容不再需要,并且驱逐它既是可能的并且提供了加速,那不是已经包含在优化器中了吗?
  • @PasserBy,也许它太难证明了,所以优化器不会走那么远。简而言之,这取决于具体情况:有时您很快就会在同一地址范围上进行分配,有时您不希望分配任何东西。因此程序员更容易根据具体情况做出决定。但是我们可以为 GCC/Clang 提交提案 :)

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


【解决方案1】:

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 上 @ 987654322@ 可以在缓存之间传输脏行,因此您可以在 L1D 中获取仍然脏的行,并且能够替换该数据而无需将旧数据发送到 DRAM。)

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

据我了解,在_mm_clflushopt() 之后,我需要调用_mm_sfence() 以使其非临时存储对其他内核/处理器可见。

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

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

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


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

会发生不好的事情吗?

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

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

【讨论】:

  • 我预计不会很快分配其他内容。这只是我怀疑我的程序是否正确的一个例子,所以我需要澄清在这种情况下会发生什么。
  • @SergeRogatch:如果你clflushopt 一些内存并立即释放它,那么另一个线程可能会从 malloc 获取它并将它存储的一些数据刷新到内存中。 (但可能不是因为free 可能需要使用locked 操作将内存添加到全局空闲列表,这将成为clflushopt 的障碍。)但即使可以,这也不会影响正确性。它存储的数据仍然存在。您可以 clflushopt 分配内存并由另一个线程使用,而不会影响正确性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2011-11-05
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多