我注意到许多使用操作系统特定原语实现的无锁算法,例如描述here的自旋锁(它使用Linux特定的原子原语)经常使用"cpu relax“指令。GCC可以通过以下方式实现这一点:
asm volatile("pause\n": : :"memory");具体来说,这条指令通常用于while循环自旋锁的主体中,同时等待变量设置为某个值。
C++11似乎没有提供任何可移植的"cpu_relax“类型指令。有什么原因吗?而“暂停”语句实际上有什么用处吗?
编辑:
另外,我想问:为什么C++11标准委员会不决定包括一个通用的std::cpu_relax()或其他什么?要保证便携性是不是太难了?
发布于 2014-08-08 21:22:52
PAUSE指令是特定于x86的。它是的唯一用途,处于自旋锁等待循环中,其中:
提高自旋等待循环的性能。当执行“旋-等待循环”时,处理器在退出循环时将遭受严重的性能损失,因为它检测到可能的内存顺序冲突。暂停指令向处理器提供了一个提示,表明代码序列是自旋等待循环。
另外:
在旋转等待循环中插入暂停指令大大降低了处理器的功耗。
将此指令放入自旋锁循环中的位置也是x86_64特定的。我不能代表C++11标准的民间人士,但我认为他们有理由得出这样的结论:正确的地方是在相关的图书馆.以及实现atomics、互斥等所需的所有其他魔法。
NB: PAUSE做而不是,释放处理器以允许另一个线程运行。这是,而不是,是“低级”pthread_yield()。(尽管在Intel超线程内核上,它确实防止了自旋锁线程占据核心。)PAUSE的基本功能似乎是关闭通常的指令执行优化和流水线,这会减缓线程的速度(有点),但是在发现锁很忙之后,这就降低了访问锁变量的速率,这样缓存系统就不会受到服务生的冲击,而当前的锁所有者正试图继续实际的工作。
请注意,用于“手摇”自旋锁、互斥锁等的原语不是操作系统特定的,而是处理器特定的。
我不确定我会把“手卷”自旋锁描述为“无锁”!
对于自旋锁的Intel建议(“Intel 64和IA-32架构优化参考手册”)是:
Spin_Lock:
CMP lockvar, 0 // Check if lock is free.
JE Get_lock
PAUSE // Short delay.
JMP Spin_Lock
Get_Lock:
MOV EAX, 1
XCHG EAX, lockvar // Try to get lock.
CMP EAX, 0 // Test if successful.
JNE Spin_Lock显然,我们可以使用std::atomic_flag编写编译的东西.或者使用pthread_spin_lock(),它在我的机器上是:
pthread_spin_lock:
lock decl (%rdi)
jne wait
xor %eax, %eax
ret
wait:
pause
cmpl $0, (%rdi)
jg pthread_spin_lock
jmp wait这是很难错的真的。
https://stackoverflow.com/questions/25189839
复制相似问题