考虑以下代码段:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define ARRAYSIZE(arr) (sizeof(arr)/sizeof(arr[0]))
inline void
clflush(volatile void *p)
{
asm volatile ("clflush (%0)" :: "r"(p));
}
inline uint64_t
rdtsc()
{
unsigned long a, d;
asm volatile ("cpuid; rdtsc" : "=a" (a), "=d" (d) : : "ebx", "ecx");
return a | ((uint64_t)d << 32);
}
inline int func() { return 5;}
inline void test()
{
uint64_t start, end;
char c;
start = rdtsc();
func();
end = rdtsc();
printf("%ld ticks\n", end - start);
}
void flushFuncCache()
{
// Assuming function to be not greater than 320 bytes.
char* fPtr = (char*)func;
clflush(fPtr);
clflush(fPtr+64);
clflush(fPtr+128);
clflush(fPtr+192);
clflush(fPtr+256);
}
int main(int ac, char **av)
{
test();
printf("Function must be cached by now!\n");
test();
flushFuncCache();
printf("Function flushed from cache.\n");
test();
printf("Function must be cached again by now!\n");
test();
return 0;
}
在这里,我尝试刷新指令缓存以删除“func”的代码,然后期望下次调用 func 时会产生性能开销,但我的结果与我的期望不符:
858 ticks
Function must be cached by now!
788 ticks
Function flushed from cache.
728 ticks
Function must be cached again by now!
710 ticks
我正期待着CLFLUSH http://x86.renejeschke.de/html/file_module_x86_id_30.html还刷新指令缓存,但显然,它没有这样做。有人可以解释这种行为或建议如何实现所需的行为。
你的代码几乎没有做任何事情func
,你所做的一点点就会被内联到test
,并且可能已经优化,因为您从不使用返回值。
gcc -O3 给我 -
0000000000400620 <test>:
400620: 53 push %rbx
400621: 0f a2 cpuid
400623: 0f 31 rdtsc
400625: 48 89 d7 mov %rdx,%rdi
400628: 48 89 c6 mov %rax,%rsi
40062b: 0f a2 cpuid
40062d: 0f 31 rdtsc
40062f: 5b pop %rbx
...
因此,您正在测量这两个移动的时间,这在硬件方面非常便宜 - 您的测量可能会显示以下延迟cpuid
这是相对昂贵的..
更糟糕的是,你的clflush
实际上会冲水test
同样,这意味着您下次访问它时要支付重新获取的惩罚,这超出了rdtsc
配对,因此不进行测量。另一方面,测量的代码依次跟随,因此获取test
可能还会获取您测量的刷新代码,因此它实际上可以在您测量时被缓存。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)