Mic*_*eyn 12 visual-c++ visual-c++-2010
由于VC++ 2010在64位代码中不支持内联汇编,因此如何在代码中获取pausex86-64指令?像有许多其他常见的汇编指令(例如,似乎没有成为一个内在此__rdtsc(),__cpuid()等...).
在为什么一面,我希望在指令帮助忙等待的使用情况,从而使(超线程)的CPU可用来上运行的其他线程CPU说(见:成效分析在intel.com).该pause指令对于此用例以及自旋锁实现非常有用,我无法理解为什么MS不将其作为内在包含.
谢谢
Mic*_*eyn 14
哇,这是一个非常难以追查的问题,但万一其他人需要x86-64 pause指令:
在YieldProcessor()从宏观windows.h扩展到未记录的_mm_pause内在的,这最终扩展到pause32位和64位代码指令.
顺便说一句,对于在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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,每个暂停指令似乎平均在Nehalem架构上产生大约9个周期的延迟(即3.3 GHz CPU上的3 ns).
该_mm_pause()征是由英特尔完全记录,并通过所有可移植操作系统跨越的主要的x86编译器的支持。IDK 如果过去缺少 MS 的文档,或者如果您错过了大约 7 年。
#include <immintrin.h>并使用它。(或用于#include <emmintrin.h>SSE2 的古代编译器)。
#include <immintrin.h>
void test() {
_mm_pause();
_mm_pause();
}
Run Code Online (Sandbox Code Playgroud)
在所有 4 个 gcc/clang/ICC/MSVC(在 Godbolt 编译器资源管理器上)编译为这个 asm :
test(): # @test()
pause
pause
ret
Run Code Online (Sandbox Code Playgroud)
在没有 SSE2 的 CPU 上,它解码为rep nop只是一个nop. x86暂停指令的跨平台实现
Gcc 甚至知道这一点,并且_mm_pause()在使用-mno-sse. (通常 gcc 和 clang 拒绝未启用的指令的内在指令,不像 MSVC。)有趣的是,gcc 甚至rep nop在其 asm 输出中发出,而其他三个发出pause. 当然,它们组装成相同的机器代码。
暂停使该超线程的前端在 Sandybridge 系列上空闲大约 5 个周期,直到 Skylake。在 Skylake 上,英特尔将其增加到约 100 个周期,以在自旋等待循环中节省更多功率并以可能的延迟为代价提高整体吞吐量,尤其是在超线程内核上。
在所有 CPU 上,它还可以避免在离开自旋循环时内存顺序错误推测。因此,当它最终再次重要时,它确实减少了延迟。