2016-09-24 47 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],因爲它經過上述優化後,在內部循環中不會改變。