rdtsc定时器在Linux中不准确?

__inline__ uint64_t rdtsc() { uint32_t low, high; __asm__ __volatile__ ( "xorl %%eax,%%eax \n cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx" ); __asm__ __volatile__ ( "rdtsc" : "=a" (low), "=d" (high)); return (uint64_t)high << 32 | low; } 

我在程序中使用了上面的rdtsc函数作为定时器:以下代码产生312-344个时钟周期:

  start = rdtsc(); stop = rdtsc(); elapsed_ticks = (unsigned)((stop-start)); printf("\n%u ticks\n",elapsed_ticks); 

每次我运行上面的代码,我得到不同的值。 这是为什么?

我在“intrin.h”中使用了rdtsc函数的Visual C ++中运行相同的代码。 我获得了18个时钟的恒定值。是的,每次运行都是不变的! 有人可以解释吗? 谢谢!

使用TSC获得可靠的时间戳是相当困难的。 主要问题是:

  • 在较老的多核处理器上,速率在不同内核上可能会有所不同,因为它们根据不同的负载调整时钟速度;
  • 在更新的处理器上,速度在时钟速度改变时保持不变,因此轻载内核的时序似乎比现在慢。
  • 乱序执行可能意味着当您认为寄存器不被读取时。

您的函数正在执行cpuid指令并忽略其结果,以及读取TSC,尝试缓解上一个问题。 这是一个序列化的指令,强制按序执行。 但是,这也是一个缓慢的指令,所以如果你试图测量一个非常短的时间,会影响结果。

如果我从函数中删除该指令,使其等同于您在VC ++中使用的内部函数:

 inline uint64_t rdtsc() { uint32_t low, high; asm volatile ("rdtsc" : "=a" (low), "=d" (high)); return (uint64_t)high << 32 | low; } 

那么我会得到更一致的价值,但是重新引入潜在的指令排序问题。

此外,请确保您正在编译优化(例如,如果您正在使用GCC -O3 ),否则该函数可能不会内联。

因为你的过程不是系统上唯一运行的过程。 它可能在任何时候被抢占,导致你的进程睡一会儿。