强制将缓存行迁移到另一个核心

Cur*_*ous 3 c++ concurrency x86 assembly cpu-cache

在用于x86硬件的C ++(使用平台上可用的任何低级内在函数)(例如Intel Skylake)中,是否可以将高速缓存行发送到另一个内核而无需强制该内核上的线程显式加载该行?

我的用例是在并发数据结构中。在这种情况下,在某些情况下,某个核心会在内存中经过某些地方,而这些地方可能在探寻斑点时由其他一些核心拥有。这些核心上的线程通常在条件变量中被阻塞,因此它们具有一些备用循环,可以在其中运行其他“有用的工作”。这里“有用的工作”的一个示例可能是它们将数据流式传输到另一个内核,该内核将在将来加载它们,因此加载内核不必在处理该行之前就等待该行进入其缓存。x86硬件上是否有一些可能的内在/指令可用?


__builtin_prefetch并不能很好地工作,因为出于某种原因,它最终将延迟添加回执行加载的代码中:(也许步幅配置不佳,但到目前为止我还没有取得很好的步幅。这可能会得到更好的处理,并且可以从确定最终会加载其行的其他内核确定地进行处理。

Pet*_*des 6

没有“推”;高速缓存行仅在物理核心请求后才进入该核心。(由于负载,软件预取甚至硬件预取。)

在有帮助的情况下,两个逻辑核心可以共享同一物理核心:如果某个将来负载的延迟远比吞吐量重要,那么唤醒预取辅助线程来引发情况可能不会那么恐怖。我正在想象让编写器使用条件变量或发送POSIX信号,或写入管道,或将导致OS辅助唤醒另一个线程的事情,该线程的CPU亲缘性设置为一个或两个逻辑核心,您关心的其他一些线程也固定在该线程上。


从写程序方可能要做的最好的事情是触发回写到共享(L3)缓存,以便另一个内核可以命中L3,而不是找到其他内核拥有的内核并且也必须等待写回。(或取决于uarch,用于直接核心->核心转移)

例如在Ice Lake或更高版本(或SKX)上,使用clwb强制执行回写操作,以使其干净但仍被缓存。(但是请注意,这会迫使它一直进入DRAM。)另请参见CPU缓存禁止,我建议在主流OS上可能使用设置为直写缓存的内存区域。

或者,当然也可以将写入器和读取器都固定在同一物理核心上,以便它们通过L1d进行通信。但是随后他们争夺执行资源。