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


读取和写入位于第一条缓存行的memb_one_
那么我想在位于2缓存行之后读写memb_forty_
现在我可能还想读写位于第二个缓存行中的成员,即中间行memb_ten_中的成员。这并非总是会发生。


因此,我需要经常执行步骤1和步骤2,但不一定总是执行步骤3。不幸的是,我无法更改结构的布局。

我的问题如下:在步骤1和步骤2之后,第二条缓存行(即中间的那条缓存行)是否从内存中全部检索到L1中?

据我了解,在L1中检索的高速缓存行只是通过读取/写入位于其中的结构成员而被“触摸”的。这实际上意味着在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

最佳答案

不,在您触摸第一个和第三个高速缓存行后,不能保证第二个高速缓存行位于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体系结构。 ]

关于c++ - 高速缓存行检索和大数据结构性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29358082/

10-11 22:12
查看更多