gpt4 book ai didi

assembly - cmpxchg 是否会在失败时写入目标缓存行?如果不是,它是否比自旋锁的 xchg 更好?

转载 作者:行者123 更新时间:2023-12-03 23:05:25 25 4
gpt4 key购买 nike

我假设简单的自旋锁不会进入操作系统等待这个问题的目的。
我看到简单的自旋锁通常使用 lock xchg 来实现。或 lock bts而不是 lock cmpxchg .
但不是cmpxchg如果期望不匹配,避免写入值?因此,cmpxchg 的失败尝试不是更便宜吗? ?
还是 cmpxchg即使发生故障,也写入数据并使其他内核的缓存行无效?
这个问题类似于 What specifically marks an x86 cache line as dirty - any write, or is an explicit change required? ,但它特定于 cmpxchg , 不是一般的。

最佳答案

在大多数或所有当前 Intel x86 处理器上,lock cmpxchg到内存类型为 WB 且完全包含在单个 L1D 缓存行中的位置执行如下:

  • 向 L1D 发出锁定读取请求,这使目标行处于锁定独占高速缓存一致性状态,并将请求的字节作为输入提供给执行端口之一以执行比较。 (从 P6 开始支持缓存锁定。)处于锁定状态的行不能因任何原因而无效或逐出。
  • 执行相等性比较。
  • 无论结果如何,向 L1D 发出解锁写入请求,这会将高速缓存行的状态更改为已修改并解锁该行,从而允许其他访问或一致性请求替换或使该行无效。

  • 可以使用某些性能事件或基于延迟的测量来凭经验观察第一步和最后一步。一种方法是分配大量原子变量,然后执行 lock cmpxchg在该数组的循环中。锁读请求类型是 RFO 请求类型之一。所以 L2_TRANS.RFO在大多数微架构上可靠的事件(或等效的)可用于测量对 L2 的锁定读取次数。 ( L2_TRANS.RFO 计算需求 RFO,因此最好关闭硬件预取器以避免在 L2 中出现不必要的命中。这也适用于 L2_RQSTS.RFO_*。)
    还有一些事件用于测量写回的数量,例如 L2_TRANS.L1D_WB , L2_TRANS.L2_WB , 和别的。不幸的是,这些事件中的许多事件和许多微体系结构要么计数不足、计数过多,要么准确计数,但不一定是所有/仅脏缓存行写回。因此,它们更难以推理,并且通常不可靠。
    更好的方法是执行 lock cmpxchg在特定物理核心上的阵列的一个部分上,然后将线程迁移到另一个物理核心(在同一个 L3 共享域中)并执行一个循环,在该循环中读取该部分的元素(正常读取)。如果 lock cmpxchg指令将目标行置于 M 状态,来自同一 L3 共享域中的另一个物理内核的读取请求应该在 L3 中命中,并且在 lock cmpxchg 所在内核的私有(private)缓存中命中修改被处决。这些事件可以使用 OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE 进行计数。 (或等效的),这在大多数/所有微架构上都是可靠的。
    锁定指令是一项昂贵的操作,原因有三个:(1) 需要将行置于独占状态,(2) 使行变脏(可能是不必要的),过多的写回会对执行时间产生重大影响,甚至更是如此当它们最终从长时间的读取请求中窃取主内存带宽时,甚至当写入持久内存时更是如此,并且(3)它们在架构上进行序列化,这使得指令处于关键路径上。
    英特尔有一个 patent这提出了对最后一个优化的优化,其中核心乐观地假设没有锁争用并向目标行发出推测性正常负载。如果该线路不存在于任何其他物理核心中,则该线路将在请求核心中处于独占状态。然后,当锁定指令执行并发出锁定读取请求时,该行有望仍处于独占状态,在这种情况下,锁定指令的总延迟将减少。我不知道是否有任何处理器实现了这种优化。如果实现了, L2_TRANS.RFO 的数量事件将远小于锁定的行数。

    关于assembly - cmpxchg 是否会在失败时写入目标缓存行?如果不是,它是否比自旋锁的 xchg 更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63008857/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com