【问题标题】:Fastest way to Compare And Swap (CAS) on Intel x86 CPU?在 Intel x86 CPU 上比较和交换 (CAS) 的最快方法?
【发布时间】:2014-11-20 12:27:23
【问题描述】:

我需要交换两个 8x 字节的内存区域,最有可能使用 CMPXCHG8B。但是,我想尽快做到这一点。其他线程将一直等待,直到此操作完成。我有几个与此相关的问题:

-只有当我使用多个处理器或多个内核时才需要LOCK前缀?如果可能的话,我真的想避免使用它。

-如果等待线程希望访问的内存位于不同的缓存行中,我是否能够基于 MESI 协议“锁定”而不使用 LOCK 前缀?

我在单处理器(多核)上运行,但如果有差异,我们非常欢迎向多处理器系统解释差异的答案。

【问题讨论】:

  • 对于本次讨论,“处理器”==“核心”。
  • 我认为CMPXCHG8B 在这种情况下不会对您有太大帮助,因为它只会交换寄存器和内存,而不是两个内存区域。你也许可以重写你的代码,这样你只需要交换 2 个连续的指针,或者使用互斥体。

标签: performance assembly x86 latency cpu-architecture


【解决方案1】:

如果您有多个处理器或多个内核,并且希望同步安全地访问共享变量,则无法避免 LOCK。 (使用 XCHG 并不能避免锁;它只是隐藏在指令中)。

按照 Jester 的提示,我很想将您的两个内存块命名为“Left”和“Right”,并使用 FLAG 动态重命名它们,例如

    GetLeft:  if LSB(FLAG)   ; least significant bit
              Read Left
              else Read Right

    GetRight: if LSB(FLAG)
              Read Right
              else Read Left

然后下面的代码将尽快“交换”它们:

    SwapLeftAndRight: 
               LOCK INC FLAG   ; flips LSB of flag

这消除了对互斥体的任何需求。 (如果您的线程试图更新这些区域,那么无论您做什么都需要互斥锁。

如果访问速度真的很关键,那么他关于将两个连续指针交换为 LEFT 和 RIGHT 的提示非常好。

【讨论】:

  • 另外注意,可以交换一对8字节的区域;但它们必须是连续的,并且 CPU 必须支持 cmpxchg16b 指令(仅在 64 位代码中支持,并且在一些早期的 64 位 CPU 上不支持)。
猜你喜欢
  • 2010-09-14
  • 2011-07-09
  • 2010-09-14
  • 1970-01-01
  • 2011-07-17
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多