【问题标题】:Overhead of Spin Loop in terms of cache coherenceSpin Loop 在缓存一致性方面的开销
【发布时间】:2011-11-14 10:34:36
【问题描述】:

假设一个内核中的一个线程在一个变量上旋转,该变量将由另一个内核上运行的线程更新。我的问题是缓存级别的开销是多少。等待线程是否会缓存变量,因此在写入线程写入该变量之前不会导致总线上的任何流量?

如何减少这种开销。 x86 pause 指令有帮助吗?

【问题讨论】:

  • 我假设您指的是 SMP?
  • 是的 Eli,我指的是 SMP 系统。

标签: c linux multithreading x86 multicore


【解决方案1】:

我相信所有现代 x86 CPU 都使用MESI protocol。因此,旋转的“读取器”线程可能会以“独占”或“共享”模式缓存数据副本,在您旋转时不会产生内存总线流量。

只有当其他核心写入该位置时,它才必须执行跨核心通信。

[更新]

如果您不会长时间旋转,像这样的“自旋锁”只是一个好主意。如果变量更新之前可能需要一段时间,请改用互斥锁 + 条件变量,这将使您的线程进入睡眠状态,这样它在等待时不会增加开销。

(顺便说一句,我怀疑很多人——包括我在内——都在想“你到底想做什么?”)

【讨论】:

  • “我相信所有现代 x86 CPU 都使用 MESI 协议。” - 你为什么相信它?我认为 AMD64 是 MOESI,intel 的 numa (i*) 是 MESIF。
  • @osgx:因为我最后一次读到它是在 5 到 10 年前?我认为它不会改变基本答案,但感谢您提供的信息。
【解决方案2】:

如果您在短时间间隔内旋转锁定,您通常没问题。但是在 Linux 上有一个定时器中断(我假设在其他操作系统上类似),所以如果你旋转锁定 10 毫秒或接近它,你会看到缓存干扰。

我听说可以修改 Linux 内核以防止特定内核上的所有中断并且这种干扰消失了,但我不知道这样做涉及到什么。

【讨论】:

  • 我认为 RHEL 5 通过命令行应用程序允许 IRQ binding
  • 是的,但是“本地计时器中断”不能移动,因为它每秒至少中断 100 次线程。 (可以配置更高)如果你知道如何关闭它,我会很感兴趣。 ;)
【解决方案3】:

在两个线程的情况下,开销可能会被忽略,无论如何,做一个简单的基准测试可能是个好主意。例如,如果您实现自旋锁,线程在自旋中花费的时间。 这种对缓存的影响称为缓存行弹跳

【讨论】:

    【解决方案4】:

    我在this post 中对此进行了广泛的测试。通常开销是由自旋锁的总线锁定组件引起的,通常是指令“xchg reg,mem”或它的一些变体。由于无法避免该特定开销,因此您可以选择节省调用自旋锁的频率并在释放它之前执行绝对最少的必要工作量(一旦锁定到位)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-31
      • 2018-05-20
      • 2011-10-22
      • 2014-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多