强制将缓存行迁移到另一个核心
Force a migration of a cache line to another core
在用于 x86 硬件(例如 Intel Skylake)的 C++(使用平台上可用的任何低级内在函数)中,是否可以将缓存行发送到另一个内核而不强制该内核上的线程加载该行明确?
我的用例在并发数据结构中。在这种情况下,在某些情况下,一个核心在探测位置时会经过内存中可能由其他一些核心拥有的某些位置。这些核心上的线程通常在条件变量上被阻塞,因此它们有一些空闲周期,可以 运行 额外 "useful work"。 "useful work" 的一个示例可能是它们将数据流式传输到另一个核心,该核心将在将来加载它们,因此加载核心在处理它之前不必等待行进入它的缓存。是否有一些 intrinsic/instruction 可以在 x86 硬件上实现?
A __builtin_prefetch 并没有很好地工作,因为出于某种原因,它最终将延迟添加回执行加载的代码 :( 也许步幅配置不当,但我没有到目前为止能够取得很好的进展。这可能会得到更好的处理,并且从知道他们的线路最终可能被加载的其他核心确定性地确定。
没有"push";缓存行仅在该内核请求后才进入物理内核上的 L1d。 (因为加载、SW 预取,甚至是 HW 预取。)
2 个逻辑核心可以共享相同的物理核心,以防万一:如果某些未来负载的延迟比吞吐量重要得多,那么唤醒预取辅助线程来启动这种情况可能不会那么可怕。我在想象让作者使用条件变量或发送 POSIX 信号,或写入管道,或导致 OS 辅助唤醒另一个线程的东西,其 CPU affinity 设置为您关心的其他线程也固定到的一个或两个逻辑核心。
您可以从写入端做的最好的事情是触发写回共享 (L3) 缓存 这样另一个核心就可以进入 L3 而不是找到它拥有其他一些核心,也必须等待回写。 (或者取决于 uarch,直接核心->核心转移)
例如在 Ice Lake 或更高版本上,使用 clwb
强制回写,使其干净但仍被缓存。 (但请注意,这会强制它一直到 DRAM。).
另见 where I suggested possibly using a memory region set to write-through caching, if that's possible under a mainstream OS. See also
或者当然是将 writer 和 reader 固定到同一个物理内核,以便它们通过 L1d 进行通信。但随后他们争夺执行资源。
在用于 x86 硬件(例如 Intel Skylake)的 C++(使用平台上可用的任何低级内在函数)中,是否可以将缓存行发送到另一个内核而不强制该内核上的线程加载该行明确?
我的用例在并发数据结构中。在这种情况下,在某些情况下,一个核心在探测位置时会经过内存中可能由其他一些核心拥有的某些位置。这些核心上的线程通常在条件变量上被阻塞,因此它们有一些空闲周期,可以 运行 额外 "useful work"。 "useful work" 的一个示例可能是它们将数据流式传输到另一个核心,该核心将在将来加载它们,因此加载核心在处理它之前不必等待行进入它的缓存。是否有一些 intrinsic/instruction 可以在 x86 硬件上实现?
A __builtin_prefetch 并没有很好地工作,因为出于某种原因,它最终将延迟添加回执行加载的代码 :( 也许步幅配置不当,但我没有到目前为止能够取得很好的进展。这可能会得到更好的处理,并且从知道他们的线路最终可能被加载的其他核心确定性地确定。
没有"push";缓存行仅在该内核请求后才进入物理内核上的 L1d。 (因为加载、SW 预取,甚至是 HW 预取。)
2 个逻辑核心可以共享相同的物理核心,以防万一:如果某些未来负载的延迟比吞吐量重要得多,那么唤醒预取辅助线程来启动这种情况可能不会那么可怕。我在想象让作者使用条件变量或发送 POSIX 信号,或写入管道,或导致 OS 辅助唤醒另一个线程的东西,其 CPU affinity 设置为您关心的其他线程也固定到的一个或两个逻辑核心。
您可以从写入端做的最好的事情是触发写回共享 (L3) 缓存 这样另一个核心就可以进入 L3 而不是找到它拥有其他一些核心,也必须等待回写。 (或者取决于 uarch,直接核心->核心转移)
例如在 Ice Lake 或更高版本上,使用 clwb
强制回写,使其干净但仍被缓存。 (但请注意,这会强制它一直到 DRAM。)
另见
或者当然是将 writer 和 reader 固定到同一个物理内核,以便它们通过 L1d 进行通信。但随后他们争夺执行资源。