CPU Relax指令和C 11原语

前端之家收集整理的这篇文章主要介绍了CPU Relax指令和C 11原语前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我注意到使用特定于操作系统的原语实现的许多无锁算法,例如描述为 here的旋转锁(使用Linux特定的原子基元)通常使用“cpu relax”指令.使用GCC,可以通过以下方式实现:
asm volatile("pause\n": : :"memory");

具体来说,该指令通常用于while循环旋转锁的正文,同时等待一个变量设置为某个值.

C11似乎没有提供任何类型的便携式“cpu_relax”类型的指令.有什么理由吗? “暂停”语句实际上是否有用?

编辑:

另外,我会问:为什么C11标准委员会没有决定包含一个通用的std :: cpu_relax()或者什么?难以保证可移植性吗?

解决方法

PAUSE指令是x86特定的.它是唯一的用途是在旋转锁等待循环中,它在哪里:

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

这是很难的,真的.

猜你在找的C&C++相关文章