for迴圈提高記憶體訪問效率的做法
阿新 • • 發佈:2018-12-04
今天寫程式的時候突然想到一點,記錄一下:
計算機記憶體地址是線性排列組織的,而利用for迴圈對高維陣列結構進行遍歷處理的時候,要保證最內層for迴圈遍歷的是高維陣列的最低維度,這樣可以最大化利用CPU的cache,舉個例子:
假設有一個二維影象P(x,y),x為行數,0<=x<=M-1,y為列數,0<=y<=N-1。
若想遍歷影象內所有的畫素,寫程式的時候,有以下兩種巢狀for:
1 for(x=0;x<M;x++){ 2 for(y=0;y<N;y++){ 3 // ... 4 } 5 }
和
1 for(y=0;y<N;y++){ 2 for(x=0;x<M;x++){ 3 // ... 4 } 5 }
這兩種實現方法都能遍歷影象內畫素,但是第一種效率比第二種高。
因為資料的邏輯形式雖然是高維的,但是儲存在記憶體裡的時候卻仍是以一維線性的方式儲存的,這就造成了高維資料在記憶體中進行表示的時候,最低維的資料在記憶體中被連續儲存,而除最低維以外的其它所有維度在記憶體上是不連續的(對於上述例子,P(3,4)與P(3,5)在記憶體中是連續的,而P(3,4)和P(2,4)在記憶體中就不是連續的),訪問不連續記憶體對於CPU的cache來說很不友好,會造成較大的記憶體訪問延遲,雖然這個問題可能會被聰明的編譯器查到並在編譯時刻優化為cache-friendly的程式碼,但是保不齊有些編譯器沒有這種優化,所以在寫程式的時候還是注意一下這一點。在訪問體素塊的時候最好也要先確定一下資料邏輯形式的最低維度,然後再寫for。