测量执行单个指令的时间

Ton*_*ion 2 c time assembly instructions

有没有办法使用C或汇编程序甚至C#来准确衡量执行ADD指令所需的时间?

Jer*_*fin 11

是的,有点,但它是非平凡的,并产生几乎毫无意义的结果,至少在最合理的现代处理器上.

在相对较慢的处理器上(例如,通过Intel系列中的原始Pentium,在大多数小型嵌入式处理器上仍然如此),您只需查看处理器的数据表,它(通常)会告诉您预期会有多少个时钟周期.快速,简单,轻松.

在现代台式机(如Pentium Pro的或更高版本),生活不如此简单.这些CPU一次可以执行许多指令,只要它们之间没有任何依赖关系,就可以不按顺序执行它们.这意味着单个指令所用时间的整个概念几乎变得毫无意义.执行一条指令所花费的时间可以并且将取决于它周围的指令.

也就是说,是的,如果你真的想,你可以(通常 - 取决于处理器)测量某些东西,尽管它可以确切地说明它究竟意味着什么.即使得到这样的结果只是接近无意义而不是完全没有意义,但这并不是微不足道的.例如,在Intel或AMD芯片上,您可以使用RDTSC进行定时测量.遗憾的是,这可以如上所述不按顺序执行.要获得有意义的结果,您需要通过无法执行的指令("序列化指令")将其包围.最常见的选择是CPUID,因为它是"用户模式"(即第3环)程序可用的少数序列化指令之一.这增加了一些扭曲本身:正如英特尔所记录的那样,处理器执行CPUID的前几次,它可能需要比后续时间更长的时间.因此,他们建议您在使用序列化时序之前执行三次.因此,一般序列运行如下:

.align 16
CPUID
CPUID
CPUID
RDTSC
; sequence under test
Add eax, ebx
; end of sequence under test
CPUID
RDTSC
Run Code Online (Sandbox Code Playgroud)

然后将其与执行相同的结果进行比较,但删除了测试中的序列.当然,这遗漏了很多细节 - 至少你需要:

  1. 在每个CPUID之前正确设置寄存器
  2. 在第一个RDTSC之后保存EAX:EDX中的值
  3. 从第一个RDTSC中减去第二个RDTSC的结果

还要注意我插入的"对齐"指令 - 指令对齐也会影响时序,特别是如果涉及到一个循环.