【发布时间】:2020-04-29 04:42:21
【问题描述】:
我编写了一个基本代码来找出 nop 占用的时钟周期数。我们知道 nop 需要一个时钟周期。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int main(void)
{
uint32_t low1, low2, high1, high2;
uint64_t timestamp1, timestamp2;
asm volatile ("rdtsc" : "=a"(low1), "=d"(high1));
asm("nop");
asm volatile ("rdtsc" : "=a"(low2), "=d"(high2));
timestamp1 = ((uint64_t)high1 << 32) | low1;
timestamp2 = ((uint64_t)high2 << 32) | low2;
printf("Diff:%lu\n", timestamp2 - timestamp1);
return 0;
}
但是输出不是1。
有时是 14 或 16。
我可以知道这背后的原因吗?我有什么遗漏吗
【问题讨论】:
-
一方面,您的计时循环还包括执行 1 个
rdtsc指令的时间。 -
你怎么知道
nop需要一个周期?一些处理器可以在每个周期从指令流中删除几个,因此它们永远不会被分派并且不会消耗执行时间。 -
@LegendofPedro: 不,
-O0只会在时间间隔内放入更多垃圾,但仍然不会让第二个 RDTSC 等待先前指令的完成。或者也停止第一个 RDTSC 的运行。请参阅我关于 RDTSC 的规范答案:How to get the CPU cycle count in x86_64 from C++? -
我们知道 nop 需要一个时钟周期。 What kind of chip you got in there, a Dorito? 说真的,你在什么 CPU 上测试过这个,所以答案可以包括假设
constant_tsc,基本/参考频率(TSC)与实际核心时钟周期的详细说明?肯定不是 486 或更早的 NOP 实际上会花费 1 个周期。 -
@LegendofPedro:没错,你想要优化 asm。不,GCC/clang 不“理解” asm 模板,他们只在将结果(包括编译器生成的 asm)提供给汇编器之前扫描它以查找
"%number"操作数替换。使用-O0,您可以将low1和low2的存储空间存储到堆栈空间,而不仅仅是mov存储到其他寄存器(或者可能shl/lea存储到第二个rdtsc 之前的另一个寄存器中)。第二次看,您实际上不会在-O0的(尝试a)“定时区域”中获得更多指令,因为没有什么可以溢出/重新加载;第二个 asm 没有输入
标签: c x86 inline-assembly rdtsc cpu-cycles