高速缓存行检索和大数据结构的性能

时间:2015-03-30 23:26:52

标签: c++ multithreading performance caching g++

假设我有一个非常大的数据结构,比我硬件的缓存行大得多(参见下面的示例)。我们假设我想

  1. 读取和写入位于第一个缓存行的memb_one_
  2. 然后我想读取并写下memb_forty_之后的2个缓存行。
  3. 现在我可能还想要读取和写入位于第二个缓存行中的成员,即中间行memb_ten_中的成员。这不会永远发生。
  4. 所以我需要经常执行第1步和第2步。但并不总是第3步。不幸的是我无法改变结构的布局。

    我的问题如下:在步骤1和步骤2之后,是第二个缓存行,即中间的一个从存储器中检索到L1?

    据我所知,L1中检索到的缓存行只是读取/写入位于其中的struct成员的“触摸”。这基本上意味着只有一部分结构实例可以在L1中使用。

    如果我的理解是正确的,那么无论如何强制所有3个缓存行的请求?我想在我需要时通过在第二个缓存行上写入来避免缓存错过。

    如果没有这样的机制你认为我可以从使用后台线程共享相同的缓存并经常读取这些实例以保持缓存行“热”中受益吗?该线程永远不会写入以避免错误的共享效应或过多的数据总线流量。

     struct VeryBigStruct 
     { 
       // first cahce line..
       int memb_one_;
       ...
    
       // second cahce line..
       int memb_ten_;
       ...
    
       // third cache line
       int memb_forty_;
       ...
     }
    

    我在Linux上使用g++ 4.7 and 4.9

1 个答案:

答案 0 :(得分:1)

不,在您触摸第一个和第三个缓存行后,第二个缓存行不能保证在L1缓存中。但它可能存在,如果频繁访问它。

如果后台线程在与主线程相同的物理内核中运行,则后台线程可能只会帮助您将数据放入L1缓存中。您可以为线程设置CPU亲和力以实现此效果。

在gcc中有一个内置函数来预取内存地址以进行缓存, 它被称为:

__builtin_prefetch(&your_struct_ptr->memb_ten_, 1, 3);

或者你可以这样做:

#include <xmmintrin.h>
...
_mm_prefetch(&your_struct_ptr->memb_ten_, _MM_HINT_ET0);

见这里:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 在这里:https://software.intel.com/en-us/node/524263

[我假设你使用x86或x86-64架构。 ]