__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);

每次运行上述代码时,都会得到不同的值。这是为什么?

我在 Visual C++ 中运行了相同的代码,它在“intrin.h”中使用了 rdtsc 函数。我得到了 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),否则该函数可能不会被内联。

    关于c++ - rdtsc 计时器在 linux 中不准确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19399373/

    10-11 19:19