这些二维阵列中的哪一个有利于使用,为什么?

时间:2011-09-25 12:38:29

标签: c++ c caching

在facebook小组中,我看到了一个问题:

如果一行在下面的二维数组中占主导地位,哪一个是有利的,为什么?

a) for(i=0;i<1000;i++)
      for(j=0;j<1000;j++)
           temp=temp+a[i][j];

b) for(j=0;j<1000;j++)
      for(i=0;i<1000;i++)
         temp=temp+a[i][j]

从我的观点来看,我可以看出上述两个陈述没有区别。我猜这些都是一样的。

如果我错了,请纠正我?

5 个答案:

答案 0 :(得分:6)

理论上没有区别。

实际的优势在于缓存局部性。如果访问距离较远的位置,则会增加缓存未命中数,从而导致代码运行速度变慢。

根据您的处理器缓存大小,您可能需要使用一些相当大的数字替换1000才能感知效果。

答案 1 :(得分:2)

Variant(a)更好,因为它比(b)更加缓存友好:您访问连续元素,因此缓存未命中次数较少。但是,一些编译器可以重新排列循环,因此在编译时,两个变体可能会生成相同的机器代码。

除了性能之外,这两种变体之间没有区别,即产生相同的输出。

答案 2 :(得分:2)

然而,情有可能是情有可原的。例如,如果数字既是正数又是负数,那么它们可能存在模式,使得一个顺序会导致溢出(或浮点时精度损失),而另一个顺序会表现得更好。

答案 3 :(得分:1)

当CPU想要从内存中读取数据/代码时,数据块或从内存移动到缓存。缓存比RAM快得多,而且要贵得多,所以你几乎没有。这背后的想法是,通常当你读取内存的一部分时,你可能会读到与其相近的其他部分。

在方法a中,您逐行读取数组,因此保留了局部性。也就是说,在从行开始的第一次读取时,该行被加载到缓存中,并且该行的其余部分从缓存中读取(缓存命中),因此您具有高缓存命中率,这是好的。

在方法b中,您故意以不连续的方式访问数组,因此您会遇到大量缓存未命中,并且您需要始终保持对内存的读取。

答案 4 :(得分:0)

根据我的说法,正确的一个是'A':因为当我们使用2-D数组时,很容易评估元素逐行缓存,而不是逐列, 由于Cache用于快速评估,如果命中率高于它的行为速度快,那么第一个是正确的,          感谢名单              祝你有愉快的一天。