clflush不刷新指令缓存

clflush not flushing the instruction cache

本文关键字:指令缓存 刷新 clflush      更新时间:2023-10-16

考虑以下代码段:

#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