假设我有一个非常大的数据结构,比我硬件的缓存行大得多(参见下面的示例)。我们假设我想
memb_one_
memb_forty_
之后的2个缓存行。memb_ten_
中的成员。这不会永远发生。所以我需要经常执行第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
。
答案 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架构。 ]