【发布时间】:2019-10-15 01:30:15
【问题描述】:
我正在使用rdtsc 在 C++ 中计时多条 NOP 指令和一条 NOP 指令。但是,我没有得到执行 NOP 所需的周期数与执行的 NOP 数量成比例的增加。我很困惑为什么会这样。我的 CPU 是 Intel Core i7-5600U @ 2.60Ghz。
代码如下:
#include <stdio.h>
int main() {
unsigned long long t;
t = __rdtsc();
asm volatile("nop");
t = __rdtsc() - t;
printf("rdtsc for one NOP: %llu\n", t);
t = __rdtsc();
asm volatile("nop; nop; nop; nop; nop; nop; nop;");
t = __rdtsc() - t;
printf("rdtsc for seven NOPs: %llu\n", t);
}
我得到的值如下:
rdtsc for one NOP: 78
rdtsc for seven NOPs: 91
rdtsc for one NOP: 78
rdtsc for seven NOPs: 78
在未设置处理器亲和性的情况下运行时。
像$ taskset -c 0 ./nop$ 这样设置处理器亲和性时,结果是:
rdtsc for one NOP: 78
rdtsc for seven NOPs: 78
rdtsc for one NOP: 130
rdtsc for seven NOPs: 169
rdtsc for one NOP: 78
rdtsc for seven NOPs: 143
为什么会这样?
【问题讨论】:
-
对于 x86 以及您编写基准的方式,这不足为奇。你真正想做的是什么?
-
我试图在十分之一微秒范围内睡觉。但是当我使用
nanosleep,睡眠间隔设置为甚至一个纳秒时,nanosleep的执行最终会花费>20000 个周期(根据rdtsc)。这就是为什么我尝试使用 nops 直接导致非常小的延迟。 -
您可能需要
pause指令。它在 Skylake 及更高版本上闲置约 100 个周期,或在早期的 Intel 内核上闲置约 5 个周期。或旋转 RDTSC。在具有巨大重新排序缓冲区的现代超标量/无序 x86 上,插入 NOP 永远不会可靠地工作!您的“睡眠”时间甚至不一定长到足以耗尽乱序执行缓冲区(ROB)。说明没有成本,您可以加起来。 What considerations go into predicting latency for operations on modern superscalar processors and how can I calculate them by hand?. -
@PeterCordes 在 RDTSC 上旋转工作!
-
你不会像这样延迟工作时间代码。需要使用计时器。
标签: assembly inline-assembly processor rdtsc nop