Tim*_*Tim 8 x86 x86-64 cpu-architecture cpu-cache memory-bandwidth
这个问题专门针对现代x86-64缓存一致性架构 - 我很欣赏其他CPU的答案可能会有所不同.
如果我写入内存,MESI协议要求首先将缓存行读入缓存,然后在缓存中进行修改(将值写入缓存行,然后将其标记为脏).在较旧的写入微架构中,这将触发高速缓存行被刷新,在写回期间,被刷新的高速缓存行可能会延迟一段时间,并且一些写入组合可能在两种机制下发生(更可能是回写) .我知道这与访问相同缓存行数据的其他核心如何交互 - 缓存监听等.
我的问题是,如果商店恰好匹配缓存中已有的值,如果没有单个位被翻转,那么任何英特尔微架构都会注意到这一点并且不将该行标记为脏,从而可能将该行标记为独占,以及在某些时候跟随的回写内存开销?
当我向更多的循环进行矢量化时,我的矢量化操作组合基元不会明确地检查值的变化,并且在CPU/ALU中这样做似乎很浪费,但我想知道底层缓存电路是否可以在没有显式编码的情况下完成(例如,商店微操作或缓存逻辑本身).由于跨多个内核的共享内存带宽变得更加成为资源瓶颈,这似乎是一种越来越有用的优化(例如,重复调整相同的内存缓冲区 - 如果它们已经存在,我们不会重新读取RAM中的值在缓存中,但强制写回相同的值似乎很浪费).回写缓存本身就是对这类问题的承认.
我可以礼貌地要求阻止"在理论上"或"它确实无关紧要"的答案 - 我知道记忆模型是如何工作的,我正在寻找的是关于如何写出相同价值的硬性事实(而不是避免一个商店)将影响内存总线的争用你可以安全地假设是一台运行多个工作负载的机器几乎总是受内存带宽限制.另一方面,解释为什么芯片不这样做的确切原因(我悲观地假设他们没有这样做)将具有启发性......
更新: 这里的预期线路上的一些答案https://softwareengineering.stackexchange.com/questions/302705/are-there-cpus-that-perform-this-possible-l1-cache-write-optimization但仍然很多推测"它必须很难,因为它没有完成",并说如何在主CPU核心中这样做会很昂贵(但我仍然想知道为什么它不能成为实际缓存逻辑本身的一部分).
可以在硬件中实现,但我认为没有人这样做。为每个商店都这样做要么会花费缓存读取带宽,要么需要额外的读取端口并使流水线变得更加困难。
您将构建一个执行读取/比较/写入循环而不是仅写入的缓存,并且可以有条件地将行保留在 Exclusive 状态而不是 Modified (MESI)。这样做(而不是在它仍然共享时检查)仍然会使该行的其他副本无效,但这意味着没有与内存排序的交互。当内核拥有缓存线的独占所有权时,(静默)存储变得全局可见,就像它已经翻转到修改然后通过写回 DRAM 返回独占一样。
读取/比较/写入必须以原子方式完成(您不能丢失读取和写入之间的缓存线;如果发生这种情况,比较结果将是陈旧的)。这使得从存储队列传输到 L1D 的数据变得更加困难。
在多线程程序中,作为软件中仅针对共享变量的优化,这样做是值得的。
避免使其他人的缓存无效可以使其值得转换
shared = x;
Run Code Online (Sandbox Code Playgroud)
进入
if(shared != x)
shared = x;
Run Code Online (Sandbox Code Playgroud)
我不确定这里是否有内存排序的影响。显然,如果shared = x永远不会发生,则没有发布序列,因此您只有获取语义而不是发布。但是,如果您存储的值通常是已经存在的值,那么将其用于订购其他东西的任何用途都会出现 ABA 问题。
IIRC,Herb Sutter 在他的原子武器:C++ 内存模型和现代硬件谈话的第 1 或 2 部分中提到了这种潜在的优化。(几个小时的视频)
这当然对于共享变量以外的任何软件来说都太昂贵了,其中写入它们的成本是其他线程中的许多延迟周期(缓存未命中和内存顺序错误推测机器清除:延迟和吞吐量成本是多少生产者-消费者在超级兄弟姐妹与非超级兄弟姐妹之间共享内存位置?)
相关:有关一般 x86 内存带宽的更多信息,尤其是 NT 与非 NT 存储的内容,以及“延迟绑定平台”为何多核至强上的单线程内存带宽低于四核至强处理器,请参阅此答案。核心,即使来自多个核心的总带宽更高。
目前没有实现x86(或任何其他ISA,据我所知)支持优化静默存储.
对此进行了学术研究,甚至还有一项关于"消除共享内存缓存一致性协议中的静默存储无效传播"的专利.(谷歌搜索'"静音商店"缓存'如果你对更多感兴趣.)
对于x86,这会干扰MONITOR/MWAIT; 某些用户可能希望监控线程在静默存储上唤醒(可以避免失效并添加"触摸"一致性消息).(目前MONITOR/MWAIT享有特权,但未来可能会发生变化.)
类似地,这可能会干扰事务存储器的一些巧妙使用.如果内存位置用作保护以避免显式加载其他内存位置,或者在支持此类内容的架构中(例如在AMD的高级同步工具中),则从读取集中删除受保护的内存位置.
(Hardware Lock Elision是一种非常有限的静默ABA存储库消除实现.它具有明确请求检查值一致性的实现优势.)
在性能影响/设计复杂性方面也存在实施问题.这样会禁止避免读取所有权(除非静默存储库消除仅在高速缓存行已经存在于共享状态时才有效),尽管目前还没有实现读取所有权避免.
无声商店特殊处理也将实现复杂的存储一致性模型(可能尤其是86的相对强劲的模型).这样做也可能会增加因一致性失败的猜测而导致回滚的频率.如果沉默的商店只支持L1-本线,时间窗口将是非常小的和回滚极为罕见的; 存储在L3或内存中缓存行可能会将频率增加到非常罕见,这可能会使其成为一个值得注意的问题.
高速缓存行粒度的沉默也比访问级别的静默少,因此避免的失效数量会更少.
额外的缓存带宽也是一个问题.目前,英特尔仅在L1高速缓存上使用奇偶校验,以避免对小写入进行读取 - 修改 - 写入.要求每个写入都具有读取以便检测静默存储将具有明显的性能和功率影响.(此类读取可能仅限于共享缓存行,并且可以机会性地执行,利用没有完全缓存访问利用率的循环,但这仍然会产生电源成本.)这也意味着如果读取 - 修改 - 写入支持是已经存在L1 ECC支持(该功能会让一些用户满意).
我对静音商店消除没有很好的阅读,所以可能还有其他问题(和解决方法).
由于已经采取了许多低调的性能改进成果,更难以实现,更不利于优势,以及不太普遍的优化变得更具吸引力.由于静态存储优化随着更高的核间通信变得更加重要,并且随着更多核心被用于处理单个任务,核心间通信将增加,因此这样的值似乎可能增加.
我发现证据表明,英特尔的一些现代 x86 CPU,包括 Skylake 和 Ice Lake 客户端芯片,至少可以在一种特定情况下优化冗余(静默)存储:
即,“零对零”方案。
例如,此图表显示了 Ice Lake 上的性能(圆圈,在左轴上测量)和相关性能计数器,其中不同大小的区域被归档为 0 或 1 的 32 位值:
一旦该区域不再适合 L2 缓存,写入零就有一个明显的优势:填充吞吐量几乎高出 1.5 倍。在零的情况下,我们还看到来自 L2 的驱逐几乎不是“静默”的,这表明不需要写出脏数据,而在另一种情况下,所有驱逐都是非静默的。
关于此优化的一些杂项细节:
我在这里更详细地写了这个,还有一个关于冰湖的附录,在这里更强烈地展示了这种效果。
2021 年 6 月更新:出于安全原因,英特尔提供的最新 CPU 微码版本中已禁用此优化(详细信息)。
1或者,至少用零覆盖该行的非零部分。
| 归档时间: |
|
| 查看次数: |
577 次 |
| 最近记录: |