visual如何在64位C++代码中使用暂停汇编指令

visual How do you use the pause assembly instruction in 64-bit C++ code?

本文关键字:暂停 汇编 指令 代码 64位 C++ visual      更新时间:2023-10-16

由于VC++2010不支持64位代码中的内联程序集,如何在代码中获得pause x86-64指令?这似乎不像许多其他常见的汇编指令(例如,__rdtsc()__cpuid()等(那样有内在的

在原因方面,我希望该指令有助于处理忙等待用例,这样(超线程(CPU就可以用于在所述CPU上运行的其他线程(请参阅intel.com上的Performance Insights(。pause指令对该用例以及旋转锁实现都很有帮助,我不明白MS为什么没有将其作为内部函数。

感谢

哇,这是一个很难追踪的问题,但如果其他人需要x86-64 pause指令:

来自windows.hYieldProcessor()宏扩展到未记录的_mm_pause内部,最终扩展到32位和64位代码中的pause指令。

顺便说一句,这是完全没有记录的,在MSDN中出现了YieldProcessor((的部分(对于VC++2010文档来说是不正确的(。

下面是一个YieldProcessor((宏块编译成的示例:

    19:     ::YieldProcessor();
000000013FDB18A0 F3 90                pause  
    20:     ::YieldProcessor();
000000013FDB18A2 F3 90                pause  
    21:     ::YieldProcessor();
000000013FDB18A4 F3 90                pause  
    22:     ::YieldProcessor();
000000013FDB18A6 F3 90                pause  
    23:     ::YieldProcessor();
000000013FDB18A8 F3 90                pause  

顺便说一句,在Nehalem架构上,每个暂停指令似乎平均产生大约9个周期的延迟(即,在3.3 GHz CPU上为3 ns(。

_mm_pause()内部版本由英特尔提供了完整的文档,并得到所有主流x86编译器的支持,可在操作系统间移植。IDK,如果MS的文档在过去缺乏,或者如果你在7年后错过了它。

#include <immintrin.h>并使用它。(或用于SSE2的古代编译器#include <emmintrin.h>(。

#include <immintrin.h>
void test() {
    _mm_pause();
    _mm_pause();
}

在gcc/clang/ICC/MSVC的所有4个(在Godbolt编译器资源管理器上(上编译到此asm:

test():                               # @test()
    pause
    pause
    ret

在没有SSE2的CPU上,它解码为rep nop,这只是一个nop。x86暂停指令的跨平台实现

Gcc甚至知道这一点,并且在使用-mno-sse编译时仍然接受_mm_pause()。(与MSVC不同,对于未启用的指令,gcc和clang通常会拒绝intrinisc。(有趣的是,gcc甚至在其asm输出中发出rep nop,而其他三个发出pause。当然,它们组装成相同的机器代码。


Pause在Sandybridge系列上闲置该超线程的前端约5个周期,直到Skylake。在Skylake上,Intel将其增加到约100个周期,以在旋转等待循环中节省更多功率,并以可能的延迟为代价提高整体吞吐量,尤其是在超线程内核上。

在所有CPU上,它还避免了在离开旋转循环时内存顺序的错误推测。因此,当它最终再次重要时,它确实减少了延迟。

另请参见";暂停";x86?中的指令?。