1. 程式人生 > >二維陣列按行和按列遍歷效率

二維陣列按行和按列遍歷效率

按行遍歷效率高。
對c語言而言,陣列在記憶體中是按行儲存的,按行遍歷時可以由指向陣列第一個數的指標一直往下走,就可以遍歷完整個陣列,而按列遍歷則要獲得指向每一列的第一行的元素的指標,然後每次將指標指下一行,但是指標的定址很快,所以不會有明顯的區別。按行遍歷比按列遍歷效率高體現在哪裡呢?
1、CPU快取記憶體:維基百科中有以下的內容:CPU快取記憶體(英語:CPU Cache,在本文中簡稱快取)是用於減少處理器訪問記憶體所需平均時間的部件。在金字塔式儲存體系中它位於自頂向下的第二層,僅次於CPU寄存 器。其容量遠小於記憶體,但速度卻可以接近處理器的頻率。當處理器發出記憶體訪問請求時,會先檢視快取內是否有請求資料。如果存在(命中),則不經訪問記憶體直接返回該資料;如果不存在(失效),則要先把記憶體中的相應資料載入快取,再將其返回處理器。

   快取從記憶體中抓取一般都是整個資料塊,所以它的實體記憶體是連續的,幾乎都是同行不同列的,而如果內迴圈以列的方式進行遍歷的話,將會使整個快取塊無法被利用,而不得不從記憶體中讀取資料,而從記憶體讀取速度是遠遠小於從快取中讀取資料的。

2、分頁排程:實體記憶體是以頁的方式進行劃分的,當一個二維陣列很大是如 int[128][1024],假設一頁的記憶體為4096個位元組,而每一行正好佔據記憶體的一頁,如果以列的形式進行遍歷,就會發生128*1024次的頁面排程,而如果以行遍歷則只有128次頁面排程,而頁面排程是有時間消耗的,因而排程次數越多,遍歷的時間就越長。

例子:

for(int i
=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) c[i][j] +=a[i][k] * b[k][j]

ijk巢狀的程式碼陣列a,c按行遍歷而陣列b按列遍歷,可能導致快取未命中情況增加;
ikj巢狀的程式碼則陣列a,b,c都按行遍歷;