我使用rdtsc和cpuid指令(使用易失性内联汇编指令)来测量程序的CPU周期。rdtsc指令给出了我的程序在Linux (具有速度优化-o2 -fomit-frame-pointer)和Windows (使用速度优化选项C编译器for MS Visual Studio2008(我想是它的VC9.0))上的实际结果。
最近,我实现了一个新的程序,它使用了大量的表查找和类似的东西。然而,在Linux上对这个带有gcc优化的程序进行的rdtsc测量总是导致错误的测量(非常少的CPU周期),比我预期的要少。在Windows上运行同一程序(使用我上面提到的优化和编译器编译)的rdtsc测量结果是真实的,符合预期。
我的问题是,有没有办法把gcc优化的易失性汇编指令移到哪里去产生上述行为呢?
我的定时器代码如下:
#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")如果有人能对此提出一些建议,我将不胜感激。
谢谢,
发布于 2012-05-10 00:02:22
为了防止内联asm函数跨任何加载/存储/其他操作移动,您应该将rdtsc编写为__asm__ __volatile__,并将"memory"包含在clobber列表中。如果不执行后一种操作,将阻止GCC删除asm或在可能需要asm的结果(或更改输入)的任何指令之间移动它,但它仍然可以相对于不相关的操作移动它。"memory"拦截器意味着,对于内存内容(其地址可能被泄漏的任何变量)在整个asm中保持不变,GCC不能做出任何假设,因此移动它变得更加困难。然而,GCC可能仍然能够在指令之间移动asm,这些指令只修改地址从未被获取的局部变量(因为它们不是"memory")。
哦,正如wildplasser在评论中所说的那样,在你在这上面浪费很多时间之前,应该检查一下asm的输出。
发布于 2012-05-11 01:09:40
我不知道它是否正确,但我曾经使用的代码是:
#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;
}我记得在Intel上比在AMD上“慢”。YMMV.
https://stackoverflow.com/questions/10518547
复制相似问题