_mm_pause()
内在函数由英特尔完整记录,并得到所有主要 x86 编译器的支持,可跨操作系统移植。IDK 如果 MS 的文档过去缺少,或者您只是错过了大约 7 年。
#include <immintrin.h>
并使用它。#include <emmintrin.h>
(或者对于SSE2的古代编译器)。
#include <immintrin.h>
void test() {
_mm_pause();
_mm_pause();
}
在所有 4 个 gcc/clang/ICC/MSVC 上编译成这个 asm(在 Godbolt 编译器资源管理器上):
test(): # @test()
pause
pause
ret
在没有 SSE2 的 CPU 上,它解码为rep nop
which is just a nop
. x86暂停指令的跨平台实现
Gcc 甚至知道这一点,并且_mm_pause()
在使用-mno-sse
. (与 MSVC 不同,通常 gcc 和 clang 拒绝 intriniscs 未启用的指令。)有趣的是,gcc 甚至rep nop
在其 asm 输出中发出,而其他三个发出pause
。当然,它们组装成相同的机器代码。
暂停使该超线程的前端在 Sandybridge 系列上闲置约 5 个周期,直到 Skylake。在 Skylake 上,英特尔将其增加到约 100 个周期,以在自旋等待循环中节省更多功率,并以可能的延迟为代价提高整体吞吐量,尤其是在超线程内核上。
在所有 CPU 上,它还避免了离开自旋循环时的内存顺序错误推测。因此,当它最终再次重要时,它确实减少了延迟。
另请参阅x86 中“PAUSE”指令的目的是什么?.