每个内存地址根据地址的模运算“映射”到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” - 请随意纠正。
答案 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]
但如上所述 - 同一次迭代中的访问会转到不同的集合,这可能会带来一些好处。