多线程 – 何时使用测试和设置或测试和测试?
x86下的并行编程可能很难,尤其是在多核CPU下.
假设我们有多核x86 CPU和更多不同的多线程通信组合. >单一作家和单一读者 那么哪一个模型更好(更有效)来锁定共享内存区域:测试和设置或测试&测试和设置以及何时使用它! 这里我有两个简单(没有时间限制)的测试程序,用x86汇编程序在Delphi IDE下编写: procedure TestAndSet(const oldValue,newValue: cardinal; var destination); asm //eax = oldValue //edx = NewLockValue //ecx = destination = 32 bit pointer on lock variable 4 byte aligned @RepeatSpinLoop: push eax //Save lock oldValue (compared) pause //CPU spin-loop hint lock cmpxchg dword ptr [ecx],edx pop eax //Restore eax as oldValue jnz @RepeatSpinLoop //Repeat if cmpxchg wasn't successful end; procedure TestAndTestAndSet(const oldValue,newValue: cardinal; var destination); asm //eax = oldValue //edx = NewLockValue //ecx = destination = 32 bit pointer on lock variable 4 byte aligned @RepeatSpinLoop: push eax //Save lock oldValue (compared) @SpinLoop: pause //CPU spin-loop hint cmp dword ptr [ecx],eax //Test betfore test&set jnz @SpinLoop lock cmpxchg dword ptr [ecx],edx pop eax //Restore eax as oldValue jnz @RepeatSpinLoop //Repeat if cmpxchg wasn't successful end; 编辑: 英特尔在文档中提到了两种方法Test& Set或Test& Test& Set.我不会在哪种情况下建立更好的方法,所以何时使用它.检查:Intel 解决方法
TTAS(#2)是一种很好的做法.在潜在CAS之前“潜伏”并等待“机会”是Java和.NET并发类中的常见做法.有了这个说法,cmpxchg在过去几年中得到了很多优化,所以你可能会在最新的处理器上获得几乎相同的结果.
在这两种情况下你应该尝试的是,当你旋转时使用一些exponential backoff. 更新 @GJ:你应该找到some more up-to-date documentation on Intel’s site.注意自486以来没有锁定总线的段落以及xchg和cmpxchg的对比图表明它们实际上是相同的. 在读取与锁定指令上旋转仍然是一个好主意,以避免在独占模式下获取高速缓存行时的一些争用. (所以TTAS.) 然而,只有在您实施例如,这将提供有用的增益.指数后退,甚至在一段时间后产生CPU. 如果您使用单个现代多核CPU,并且核心之间具有共享L3缓存,那么TTAS和TAS之间的差异,或者无退避将会更小,如果您使用的是多插槽,则会更加明显 – 例如服务器 – 机器或核心之间没有共享缓存的多核CPU.根据争用的数量,它们也会有所不同. (即轻载会看到TTAS / TAS之间的差异较小.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |