首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CPU松弛指令和C++11原语

CPU松弛指令和C++11原语
EN

Stack Overflow用户
提问于 2014-08-07 18:42:41
回答 1查看 7.2K关注 0票数 17

我注意到许多使用操作系统特定原语实现的无锁算法,例如描述here的自旋锁(它使用Linux特定的原子原语)经常使用"cpu relax“指令。GCC可以通过以下方式实现这一点:

代码语言:javascript
运行
复制
asm volatile("pause\n": : :"memory");

具体来说,这条指令通常用于while循环自旋锁的主体中,同时等待变量设置为某个值。

C++11似乎没有提供任何可移植的"cpu_relax“类型指令。有什么原因吗?而“暂停”语句实际上有什么用处吗?

编辑:

另外,我想问:为什么C++11标准委员会不决定包括一个通用的std::cpu_relax()或其他什么?要保证便携性是不是太难了?

EN

回答 1

Stack Overflow用户

发布于 2014-08-08 21:22:52

PAUSE指令是特定于x86的。它是的唯一用途,处于自旋锁等待循环中,其中:

提高自旋等待循环的性能。当执行“旋-等待循环”时,处理器在退出循环时将遭受严重的性能损失,因为它检测到可能的内存顺序冲突。暂停指令向处理器提供了一个提示,表明代码序列是自旋等待循环。

另外:

在旋转等待循环中插入暂停指令大大降低了处理器的功耗。

将此指令放入自旋锁循环中的位置也是x86_64特定的。我不能代表C++11标准的民间人士,但我认为他们有理由得出这样的结论:正确的地方是在相关的图书馆.以及实现atomics、互斥等所需的所有其他魔法。

NB: PAUSE而不是,释放处理器以允许另一个线程运行。这是,而不是,是“低级”pthread_yield()。(尽管在Intel超线程内核上,它确实防止了自旋锁线程占据核心。)PAUSE的基本功能似乎是关闭通常的指令执行优化和流水线,这会减缓线程的速度(有点),但是在发现锁很忙之后,这就降低了访问锁变量的速率,这样缓存系统就不会受到服务生的冲击,而当前的锁所有者正试图继续实际的工作。

请注意,用于“手摇”自旋锁、互斥锁等的原语不是操作系统特定的,而是处理器特定的。

我不确定我会把“手卷”自旋锁描述为“无锁”!

对于自旋锁的Intel建议(“Intel 64和IA-32架构优化参考手册”)是:

代码语言:javascript
运行
复制
  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(),它在我的机器上是:

代码语言:javascript
运行
复制
  pthread_spin_lock:
    lock decl (%rdi)
    jne    wait
    xor    %eax, %eax
    ret
  wait:
    pause
    cmpl   $0, (%rdi)
    jg     pthread_spin_lock
    jmp    wait

这是很难错的真的。

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25189839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档