假设一个核心中的一个线程正在旋转一个变量,该变量将由另一个核心上运行的线程更新。我的问题是缓存级别的开销是多少。等待线程是否会缓存变量,因此在写入线程写入该变量之前不会导致总线上的任何流量?
如何减少这种开销。 x86 pause
指令有帮助吗?
答案 0 :(得分:3)
我相信所有现代x86 CPU都使用MESI protocol。因此,旋转的“阅读器”线程可能会以“独占”或“共享”模式获得数据的缓存副本,在您旋转时不会产生内存总线流量。
只有当其他核心写入该位置时,才会执行跨核心通信。
[更新]
像这样的“旋锁”只是一个好主意,如果你不会旋转很长时间。如果在变量更新之前可能需要一段时间,请使用互斥+条件变量,这将使您的线程处于休眠状态,以便在等待时不会增加开销。(顺便说一下,我怀疑很多人 - 包括我 - 都在想“你究竟想做什么?”)
答案 1 :(得分:1)
如果您在短时间内旋转锁定,通常会很好。但是在Linux上有一个定时器中断(我假设在其他操作系统上类似),所以如果您将锁定旋转10毫秒或接近它,您将看到缓存干扰。
我听说有可能修改Linux内核以防止特定内核上的所有中断,这种干扰消失了,但我不知道这样做有什么用。
答案 2 :(得分:0)
在两个线程的情况下,开销可能会被忽略,无论如何,做一个简单的基准测试可能是一个好主意。例如,如果你实现自旋锁,那么线程花费多少时间进入旋转。 这种对缓存的影响称为缓存行弹跳。
答案 3 :(得分:0)
我在this post进行了广泛的测试。一般来说,开销是由自旋锁的总线锁定组件引起的,通常是指令“xchg reg,mem”或其中的一些变体。由于无法避免这种特殊的开销,因此您可以选择节省调用自旋锁的频率,并在释放锁之前执行必要的绝对最小工作量。