由于数据的物理布局导致缓存性能下降

时间:2014-05-18 05:06:27

标签: c++ performance optimization cpu-architecture cpu-cache

每个内存地址根据地址的模运算“映射”到CPU缓存中自己的缓存集。

有没有办法访问两个大小相同的数组,如下所示:

int* array1;  //How does the alignment affect the possibility of cache collisions?
int* array2;

for(int i=0; i<array1.size(); i++){
    x = array1[i] * array2[i];   //Can these ever not be loaded in cache at same time?
}

会导致性能下降,因为array1 [i]和array2 [i]中的元素给出相同的缓存行模数结果?或者,这实际上会增加性能,因为只需要加载一个缓存行来获取两个数据位置?

是否有人能够举例说明由于缓存映射而导致的性能变化,包括数组对齐如何影响?

(我的问题的原因是我试图了解何时由于数据对齐/地址映射到同一缓存行而导致性能问题,导致其中一条数据不存储在缓存中)

注意:我可能混淆了术语缓存“line”和“set” - 请随意纠正。

1 个答案:

答案 0 :(得分:0)

现在你的代码没有多大意义,因为你没有为数组分配任何内存。指针只是2个未初始化的变量,它们坐在堆栈上并且什么都没有指向。另外,指向int *的指针实际上没有size()函数。

假设你解决了所有问题,如果你做了分配,你可以决定是否连续分配数据。您可以为一个指针分配2 * N个整数,并将另一个指向该区域的中间位置。

这里的主要考虑因素是 - 如果数组足够小以至于不包围所需的缓存级别,那么连续映射它们将避免必须在它们之间共享相同的缓存集。这可以提高性能,因为由于硬件考虑,对同一组的同时访问通常是非最佳的。

颠簸的考虑(两个数组是否会将其他线路从缓存中抛出)不是一个问题,因为今天大多数缓存都享有某种程度的关联性 - 这意味着数组可以映射到相同的集合但是生活在不同的缓存方式。如果数组太大并且超过了总路径数,那么这意味着它们的地址范围会多次绕过缓存集映射,在这种情况下,如果它对齐起来并不重要,你仍然会发生碰撞与另一个数组的一些行

例如,如果你在缓存中有4组和2种方法,并尝试使用对齐偏移映射2个64个整数的数组,你仍然会填写整个缓存 -

          way0        way1     
set 0   array1[0]   array2[32]
set 1   array1[16]  array2[48]
set 2   array1[32]  array2[0]
set 3   array1[48]  array2[16]

但如上所述 - 同一次迭代中的访问会转到不同的集合,这可能会带来一些好处。