clflush不刷新指令缓存
clflush not flushing the instruction cache
考虑以下代码段:
#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 ticksn", 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也会刷新指令缓存,但显然没有这么做。有人能解释一下这种行为吗?或者建议一下如何实现所需的行为。
您的代码在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
可能也会获取您测量的刷新代码,因此在测量时它实际上可以被缓存。
它在我的电脑上运行良好
264 ticks
Function must be cached by now!
258 ticks
Function flushed from cache.
519 ticks
Function must be cached again by now!
240 ticks
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++:对不存在的命名空间使用命名空间指令
- cmake更新缓存的变量
- 试图对缓存进行跨步测试,但程序并没有结束
- 函数名是c中该函数的第一条指令的地址吗
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 存储指令是否会阻止缓存未命中的后续指令?
- 如何刷新CPU缓存中的地址范围?
- 有没有办法刷新与程序相关的整个CPU缓存
- 减少指令缓存错过(在C 中)
- 为什么我的代码会导致指令缓存未命中
- clflush不刷新指令缓存
- 指令高速缓存和条件语句
- 刷新缓存以防止基准测试波动
- 发布版本中的缓存刷新问题
- 原子增量正在刷新其他缓存行(提供的代码和结果)
- 缓存刷新后的计时非常不确定
- 缓存刷新例程之间的时间不一致
- 如何用C ++编写指令缓存友好程序