使用rdtsc进行gcc优化的问题

我正在使用rdtsc和cpuid指令(使用易失性内联汇编指令)来测量程序的CPU周期。 rdtsc指令为Linux上的程序(带速度优化-o2 -fomit-frame-pointer)和Windows(使用MS Visual Studio 2008的速度优化选项C编译器(我认为它的VC 9.0))提供了真实的结果。

最近,我实现了一个新程序,它使用了大量的表查找和类似的东西。 但是,在Linux上使用gcc优化的程序的rdtsc测量总是导致错误的测量(非常少的CPU周期)比我预期的。 在Windows上运行时相同程序的rdtsc测量(使用上面提到的优化和编译器编译)是现实的,并且同意了预期。

我的问题是,有什么方法gcc优化移动volatile组件指令一些产生上述行为的地方?

我的定时器代码如下:

#define TIMER_VARS \ uint32 start_lo, start_hi; \ uint32 ticks_lo, ticks_hi #define TIMER_START() \ __asm__ __volatile__ \ ("rdtsc" \ : "=a" (start_lo), "=d" (start_hi) /* a = eax, d = edx*/ \ : /* no input parameters*/ \ : "%ebx", "%ecx", "memory") #define TIMER_STOP() \ __asm__ __volatile__ \ ("rdtsc" \ "\n subl %2, %%eax" \ "\n sbbl %3, %%edx" \ : "=&a" (ticks_lo), "=&d" (ticks_hi) \ : "g" (start_lo), "g" (start_hi) \ : "%ebx", "%ecx", "memory") 

如果某个机构可以对此提出一些想法,我将非常感激。

谢谢,

为了防止内联rdtsc函数在任何加载/存储/其他操作中移动,您应该将asm写为__asm__ __volatile__并在clobber列表中包含"memory" 。 如果不执行后者,GCC将被阻止移除asm或将其移动到可能需要asm的结果(或更改输入)的任何指令,但它仍然可以针对不相关的操作移动它。 "memory"破坏意味着GCC无法对内存内容做出任何假设(任何地址可能泄漏的变量)在asm中保持不变,因此移动它变得更加困难。 但是,GCC 仍然可以将asm移动到仅修改其地址从未被占用的局部变量的指令(因为它们不是"memory" )。

哦,正如wildplasser在评论中所说,在你浪费大量时间之前检查asm输出

我不知道它是否正确,但我曾用过的代码是:

 #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) typedef unsigned unsigned long long Ull; static inline Ull myget_cycles (void) { Ull ret; rdtscll(ret); return ret; } 

我记得它在英特尔上比在AMD上“慢”。 因人而异。