在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]
从我的观点来看,我可以看出上述两个陈述没有区别。我猜这些都是一样的。
如果我错了,请纠正我?
答案 0 :(得分:6)
理论上没有区别。
实际的优势在于缓存局部性。如果访问距离较远的位置,则会增加缓存未命中数,从而导致代码运行速度变慢。
根据您的处理器缓存大小,您可能需要使用一些相当大的数字替换1000才能感知效果。
答案 1 :(得分:2)
Variant(a)更好,因为它比(b)更加缓存友好:您访问连续元素,因此缓存未命中次数较少。但是,一些编译器可以重新排列循环,因此在编译时,两个变体可能会生成相同的机器代码。
除了性能之外,这两种变体之间没有区别,即产生相同的输出。
答案 2 :(得分:2)
然而,情有可能是情有可原的。例如,如果数字既是正数又是负数,那么它们可能存在模式,使得一个顺序会导致溢出(或浮点时精度损失),而另一个顺序会表现得更好。
答案 3 :(得分:1)
当CPU想要从内存中读取数据/代码时,数据块或从内存移动到缓存。缓存比RAM快得多,而且要贵得多,所以你几乎没有。这背后的想法是,通常当你读取内存的一部分时,你可能会读到与其相近的其他部分。
在方法a中,您逐行读取数组,因此保留了局部性。也就是说,在从行开始的第一次读取时,该行被加载到缓存中,并且该行的其余部分从缓存中读取(缓存命中),因此您具有高缓存命中率,这是好的。
在方法b中,您故意以不连续的方式访问数组,因此您会遇到大量缓存未命中,并且您需要始终保持对内存的读取。
答案 4 :(得分:0)
根据我的说法,正确的一个是'A':因为当我们使用2-D数组时,很容易评估元素逐行缓存,而不是逐列, 由于Cache用于快速评估,如果命中率高于它的行为速度快,那么第一个是正确的, 感谢名单 祝你有愉快的一天。