由于VC ++ 2010在64位代码中不支持内联汇编,如何在代码中获得pause
x86-64指令?似乎没有像这样的固有的许多其他常见的汇编指令(例如,__rdtsc()
,__cpuid()
等......)。
就原因而言,我希望该指令能够帮助处理繁忙的等待用例,以便(超线程)CPU可用于在所述CPU上运行的其他线程(请参阅:intel.com上的Performance Insights) 。 pause
指令对这个用例以及自旋锁实现非常有用,我无法理解为什么MS没有将它作为内在函数包含在内。
由于
答案 0 :(得分:14)
哇,这是一个非常难以追查的问题,但是如果其他人需要x86-64 pause
指令:
YieldProcessor()
中的windows.h
宏扩展为未记录的_mm_pause
内在函数,最终扩展为32位和64位代码中的pause
指令。
顺便说一句,对于YieldProcessor()出现在MSDN中的部分(以及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)。
答案 1 :(得分:1)
_mm_pause()
intrinsic is fully documented by Intel受所有主要的x86编译器支持,可跨操作系统移植。如果过去缺少MS的文档,或者如果您只是错过了大约7年,则可以使用IDK。
#include <immintrin.h>
并使用它。 (或对于SSE2的古代编译器#include <emmintrin.h>
)。
#include <immintrin.h>
void test() {
_mm_pause();
_mm_pause();
}
在gcc / clang / ICC / MSVC(on the Godbolt compiler explorer)的全部4个上编译为该asm:
test(): # @test()
pause
pause
ret
在没有SSE2的CPU上,它解码为rep nop
,而只是nop
。 Cross-platform implementation of the x86 pause instruction
Gcc甚至知道这一点,并且在使用_mm_pause()
进行编译时仍然接受-mno-sse
。 (与MSVC不同,通常gcc和clang拒绝未启用指令的内在函数。)有趣的是,gcc甚至在其asm输出中发出rep nop
,而其他三个发出pause
。当然,它们会汇编为相同的机器代码。
暂停会在Sandybridge系列上使该超线程的前端闲置大约5个周期,直到Skylake。在Skylake上,英特尔将其增加到约100个周期,以在自旋等待循环中节省更多电量。