代码之家  ›  专栏  ›  技术社区  ›  Vlad Feinstein

\u mm\u预取是异步的吗?

  •  0
  • Vlad Feinstein  · 技术社区  · 4 年前

    有关 Understanding `_mm_prefetch`

    我明白了 _mm_prefetch() 将请求的值提取到处理器的缓存中,然后执行我的代码 虽然 一些预先获取的东西。

    但是,我的VS2017 profiler指出,5.7%用于访问我的数据库的线路 cache 平均为8.63% _mm_prefetch 线路。探查器搞错了吗?如果我在等待获取数据,我需要它做什么?我可以在下一个函数调用中等待,当我需要的时候。。。

    另一方面,总体计时显示了预取调用的显著好处。

    其他信息。

    我有多个缓存,不同的密钥宽度,最多32位密钥(我目前正在分析)。对缓存和预取的访问被提取到单独的数据库中 __declspec(noinline)

    uint8_t* cache[33];
    
    __declspec(noinline)
    uint8_t get_cached(uint8_t* address) {
        return *address;
    }
    
    __declspec(noinline)
    void prefetch(uint8_t* pcache) {
        _mm_prefetch((const char*)pcache, _MM_HINT_T0);
    }
    
    int foo(const uint64_t seq64) {
        uint64_t key = seq64 & 0xFFFFFFFF;
        uint8_t* pcache = cache[32];
        int x = get_cached(pcache + key);
        key = (key * 2) & 0xFFFFFFFF;
        pcache += key;
        prefetch(pcache);
        // code that uses x
    }
    

    int x = get_cached(pcache + key); 生产线和8.97% prefetch(pcache); ,而周围代码显示每行0.40-0.45%。

    0 回复  |  直到 4 年前
        1
  •  3
  •   BeeOnRope    4 年前

    基本上 一切 在一个无序的CPU上,按您所描述的方式是“异步的”(实际上,并行和无序运行)。从这个意义上说,预取与常规加载并没有什么不同,常规加载也可能无序运行或与其他指令“异步”运行。

    一旦理解了这一点,预取的确切行为将取决于硬件,但据我观察:

    • 他们的数据到了。因此,一条成功开始执行的预取指令不会在此之后阻塞CPU管道。但是,请注意“成功执行”:预取指令仍然需要一个行填充缓冲区(MSHR),如果它在L1中丢失,在Intel上它将等待该资源(如果不可用)。因此,如果并行发出大量预取未命中,它们最终会等待填充缓冲区,这使得它们的行为与该场景中的普通加载非常相似。

    • 在AMD-Zen[2]上,预回迁