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

标签 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] 中的元素给出相同的缓存行模结果?或者,这实际上会提高性能吗,因为只需加​​载一个高速缓存行即可获得两个数据位置?

有人能举出上面的例子来说明由于缓存映射导致的性能变化,包括数组的对齐方式会对此产生怎样的影响吗?

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

注意:我可能混淆了术语缓存“行”和“设置”- 请随时更正。

最佳答案

现在您的代码没有多大意义,因为您没有为数组分配任何内存。指针只是 2 个未初始化的变量,位于堆栈中并且指向任何内容。此外,指向 int* 的指针实际上并没有 size() 函数。

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

这里的主要考虑因素是——如果数组足够小以至于不会环绕您想要的缓存级别,让它们连续映射将避免在它们之间共享相同的缓存集。这可能会提高性能,因为出于 HW 的考虑,同时访问相同的集合通常不是最佳的。

抖动的考虑(两个数组是否会将彼此的行抛出缓存)实际上并不是问题,因为当今大多数缓存都享有某种程度的关联性——这意味着数组可以映射到相同的集合但存在于不同的缓存方式。如果数组太大并且超过了总路径数,那么这意味着它们的地址范围多次环绕缓存集映射,在这种情况下它如何对齐并不重要,你仍然会发生冲突与其他数组的一些行

例如,如果您在缓存中有 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]

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

关于c++ - 由于数据的物理布局导致缓存性能下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23718742/

相关文章:

c++ - 'look up' 关键字的最有效方法

http - 将用户的权限存储在 JWT 声明中或在每次请求时在服务器上检查它是否更有效?

c++ - 是否可以从 TreeView 的节点中删除一些复选框?

c++ - 如何对 std::vector 实现自己的功能?

sql - 性能问题 : difference between select s. * 与 select *

sql - Mysql 查询性能 -

c++ - static_assert 是否有助于优化编译器?

c++ - 编译简单的 Opt++ 示例 : Undefined reference to dswap_

c++ - 在模板链表中没有调用查找的匹配函数

c++ - 怪物阵列无法按我需要的方式工作