asm volatile("pause\n": : :"memory");
具体来说,该指令通常用于while循环旋转锁的正文,同时等待一个变量设置为某个值.
C11似乎没有提供任何类型的便携式“cpu_relax”类型的指令.有什么理由吗? “暂停”语句实际上是否有用?
编辑:
另外,我会问:为什么C11标准委员会没有决定包含一个通用的std :: cpu_relax()或者什么?难以保证可移植性吗?
解决方法
Improves the performance of spin-wait loops. When executing a “spin-wait loop,” processors will suffer a severe performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop.
也:
Inserting a pause instruction in a spinwait loop greatly reduces the processor’s power consumption.
把这个指令放在自旋锁定循环中的地方也是x86_64具体的.我不能为C 11标准民间发言,但我认为合理的结论是,这个魔法的正确的地方在相关的图书馆,以及实现原子,互斥等所需的所有其他魔法.
注意:PAUSE不会释放处理器以允许另一个线程运行.它不是一个“低级”pthread_yield(). (尽管在英特尔超线程内核上,它可以防止旋转锁定线程占用内核.)PAUSE的基本功能似乎是关闭通常的指令执行优化和流水线,这会减慢线程(有点),但是发现锁很忙时,这会降低锁定变量被触摸的速率,从而当锁的当前所有者试图重新开始实际工作时,缓存系统不会被服务员敲打.
请注意,用于“手动滚动”旋转锁定,互斥体等的原语不是操作系统特定的,而是处理器特定的.
我不知道我会将“手滚”旋锁描述为“无锁”!
FWIW,英特尔推荐的自旋锁(“英特尔®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
这是很难的,真的.