2016-09-24 84 views
1

为什么在使用MSVC++编译时版本1比版本2更快?缓存不友好的循环超过缓存友好循环的2d阵列

版本1:

for (int i = 0; i < N; ++i) 
    for (int j = 0; j < N; ++j) 
     for (int k = 0; k < N; ++k) 
      res1[i][j] += mat1[i][k] * mat2[k][j]; 

版本2:

​​

(N = 1000; RES1,MAT1,MAT2是双[N] [N]阵列)

版本2不应该更快,因为在循环内用[j] [k]在mat2上索引是缓存友好的(当将ram中的mat2 [j] [k]加载到缓存mat2 [j] [k +1],mat2 [j] [k + 2],...也会被加载,因为它们在同一个cachline上))? (如果我关闭编译器优化(使用:“#pragma optimize(”,off)“)版本2比版本1快,但代码运行速度慢很多(显然))。

编辑:

性能:

随着编译器优化(使用WINDOWS.H ==> QueryPerformanceCounter的测量的时间):版本1:〜493毫秒;版本2:954 ms 没有编译器优化:Version1:〜3868 ms;版本2:〜2266毫秒

+1

启用优化的实际数字是多少? – 2501

+0

你看过装配了吗? 'res1','mat1'和'mat2'是什么类型? – kfsone

回答

2

使用的优化,对于第一个版本,编译器可以明显地重新安排内部的两个环插入:

for (int i = 0; i < N; ++i) 
    for (int k = 0; k < N; ++k) 
     for (int j = 0; j < N; ++j) 
      res1[i][j] += mat1[i][k] * mat2[k][j];  

这将使类似于第二的第一个版本在缓存方面意识。

之所以第一个版本是两倍的速度,可能是第二项的缓存:mat1[i][k],因为它经过上述优化后,在内部循环中不会改变。