c++ - clflush 不刷新指令缓存

标签 c++ assembly x86 cpu-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 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也刷新指令缓存,但显然,它没有这样做。有人可以解释这种行为或建议如何实现所需的行为。

最佳答案

您的代码在 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 可能还会获取您测量的刷新代码,因此它实际上可以在您测量时被缓存。

关于c++ - clflush 不刷新指令缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20600798/

相关文章:

assembly - MIPS:不使用伪代码的 la 指令的等价物?

c++ - 你如何在 OSX 中使用 QT 设置 OpenCV?

c++ - 随着时间 SFML C++ 移动时每隔几秒 Sprite

assembly - 加载/存储指令中的偏移量是否可能为负数,而不是 4 的倍数?

c - 汇编零错误——switch语句

assembly - 无法将寄存器移动到不同大小的寄存器

c - 在 x86 Assembly 中组装代码时出错

assembly - Shellcoders手册中的汇编指令不一致

c++ - CUDA NPP - GPU 错误检查时出现未知错误

c++ - 指向导致问题的 std::promise 的指针