Row / Column Major
首先要瞭解:C 是 Row Maojr 的語言。
意思是:有2個一維整數陣列,它們各有3個整數。因此,在 RAM 的某處,會有
Column Major 的話則會是(如:ForTran、MatLab 和 OpenGL,Assign的方式當然也不一樣。)
意思是:有3個一維整數陣列,它們各有2個整數。
所以,在C,上例 A[0][3] 就是 A[1][0],A[0][4] 就是 A[1][1],A[0][5] 就是 A[1][2],
而 A[0][6] 就是 A[1][3] 就是 A[2][0] 就超界 = 不合法!
只要算對了,Column / Row 用反了有差嗎?
要知道多數電腦存取下一〝個〞記憶體比下 N 〝個〞記憶體快!
所以,存取完A[0][1],要存取A[0][2] 通常比存取 A[1][1]快!
因此,常連續處理的資料,要放在最後一維裡!
這在大陣列 或 O(n<sup>p</sup>)演算法裡,速度差很多!(p 越大差越多)
若是O(x<sup>n</sup>) ,那放錯順序就完蛋了:慢到暈倒!
什麼叫〝個〞呢? Byte, Word, Double Word 或 Para 都行!只要是 CPU 且 BUS 支援的定址法。
且?是的!生意手法曾出不窮!
像 8088, 80386(386希望沒記錯) 等就是〝掛羊頭賣狗肉〞的 CPU:內位元數與外位元數不同!<hr>恭禧大家,可以進入主題了。
二維陣列的種類(一):定義
C 的二維陣列有三種:int a[4][3], *b[4], **c; 雖然常常可以混用,但它們是不一樣的!
(註:4, 3 是方便下面說明用的。)
為了 a,compiler配置了 一個位置給 a,和 4*3=12 個sizeof(int)位置給整個 a[4][3]。
在存取a[2][1]時,是用 (a+2*3+1) 得到位置,去存取值。
因為,每個 a[i] 都是 3 個元素。
*b[4] 則不同。compiler 配置了一個位置給 b,還有 4 個指位置空間給整個 *b[4]。
注意,雖然b[3][1]是合法的語法,但compiler 並沒有配置空間給 b[3][1]!
所以,要先 b[3] = malloc(n);,才能讀寫 b[3][1]!(n > 1)(註:malloc 在 C++ 建議用 new)
在算b[2][1]時,是由 b[2]找到 b[2][0] 的位置,再加 1單位 找到 b[2][1]!
因為每個 b[0]、b[1]、b[2]、b[3]可以配置不同大小的東東,如:
所以沒辦法用 a 的算法得知 b[2][1] 的位置在哪!
那,**c 呢?它等同於前述的 compiler 配給 a 或 b 本身的東東。That's all!
沒有任何其它空間配給 c[_] 或 c[_][_]!
(和 b 一樣,配置足夠空間後,給每個c[_]初值:對應到可用的空間,就可以用了。
沒做上述處理前,c[2][1] 在 compile 時是合法的!但執行時(runtime)會出問題!)
[] 和 * 至少還有一個差別,請參 http://tw.knowledge.yahoo.com/question/?qid=1607082407793 的最佳解答與意見
二維陣列的種類(二):差別
由上可知,雖然a, b, c 都是二級指位器,但至少有五大不同:
1. 配置法: initial 時的配置(前述)
2. 找法:執行時,找 x[_][_]的方法(前述)
3. 配置區:函數內宣告的變數(不管是不是陣列、幾維),用的 RAM 是 Stack。
其它方式的變數(全域(global)、用static 修飾、或是用動態配置(malloc()系 或 new))用的 RAM 是 Heap。
4. 最大 大小:
Stack 通常都很小:幾 K(Apple][ 是 0.25K ) 到幾 M(XP 好像是 4M);
Heap 就是接近整個 RAM,有的還會含 虛擬記憶體 (VM)。
5. 速度:有些電腦,Stack 會比 Heap 快一點!
(當然也要 compiler 有用那功能才會看到差別。)
(感謝 iseeyou 在討論中提供了一個例子!
)
這個差別就算有,也不大。
不過,Stack 幾乎不會用到 VM,Heap 就很有可能!
一旦用到 VM,所有的電腦都一樣,Heap 的速度就……
malloc 的上限 http://tw.knowledge.yahoo.com/question/question?qid=1406072517903
大二維動態配置應注意事項
強列不建議用上面二維陣列的種類(一)裡示範碼的寫法,去做大的二維動態配置!
速度是大陣列的重點!二維動態配置常用在大陣列上!
配置法錯誤,速度有明顯的差異!
上面的寫法至少有五個問題:
1. 初值化時的速度:所有有在研究/大量使用malloc 的都知道:malloc 有個致命傷:很慢!!!
不管在 DOS / Windows / Linux / Unix 都一樣!
2. 使用時的速度:每個第二維的陣列都存在不同的位置,
a. 陣列本身失去 locality 的加速性!
b. 不可用跨維計算位址!
3. 比較耗 RAM:每次 malloc/new,OS會用掉另一小塊 RAM來記得這塊 RAM 分配出去了!
這個小塊 RAM 是一般程式裡看不到的!
超大陣列就在怕 RAM 不夠用了,還讓 OS 吃掉寶貴的 RAM!
嫌 RAM 太快,想用 VM 來降速?
4. 用完要 free 時,free 到昏倒!而且,free 也不快!
5. 當 parallel 時,send/receive 明顯變慢!
所以,我建議
new/malloc 二次就好!因此,也只要 delete/free 二次就好!
一次是[ROW*COLUMN],一次是 *[ROW],再用個迴圈把*[ROW]依序指到[ROW*COLUMN]裡去!
如果要速度、陣列 Size 小於(約)2M,可以用
int P[大數]
或
int P[中數][中數]
去做,速度會比 動態 的做法快!
改天我有空再補這部份
陣列 是 const pointer
http://tw.knowledge.yahoo.com/question/question?qid=1008010406774
首先要瞭解:C 是 Row Maojr 的語言。
代碼: |
int A[2][3] = { {1, 2, 3}, {4, 5, 6} }; |
代碼: |
1 2 3 4 5 6 |
代碼: |
1 4 2 5 3 6 |
所以,在C,上例 A[0][3] 就是 A[1][0],A[0][4] 就是 A[1][1],A[0][5] 就是 A[1][2],
而 A[0][6] 就是 A[1][3] 就是 A[2][0] 就超界 = 不合法!
只要算對了,Column / Row 用反了有差嗎?
要知道多數電腦存取下一〝個〞記憶體比下 N 〝個〞記憶體快!
所以,存取完A[0][1],要存取A[0][2] 通常比存取 A[1][1]快!
因此,常連續處理的資料,要放在最後一維裡!
這在大陣列 或 O(n<sup>p</sup>)演算法裡,速度差很多!(p 越大差越多)
若是O(x<sup>n</sup>) ,那放錯順序就完蛋了:慢到暈倒!
什麼叫〝個〞呢? Byte, Word, Double Word 或 Para 都行!只要是 CPU 且 BUS 支援的定址法。
且?是的!生意手法曾出不窮!
像 8088, 80386(386希望沒記錯) 等就是〝掛羊頭賣狗肉〞的 CPU:內位元數與外位元數不同!<hr>恭禧大家,可以進入主題了。

二維陣列的種類(一):定義
C 的二維陣列有三種:int a[4][3], *b[4], **c; 雖然常常可以混用,但它們是不一樣的!
(註:4, 3 是方便下面說明用的。)
為了 a,compiler配置了 一個位置給 a,和 4*3=12 個sizeof(int)位置給整個 a[4][3]。
在存取a[2][1]時,是用 (a+2*3+1) 得到位置,去存取值。
因為,每個 a[i] 都是 3 個元素。
*b[4] 則不同。compiler 配置了一個位置給 b,還有 4 個指位置空間給整個 *b[4]。
注意,雖然b[3][1]是合法的語法,但compiler 並沒有配置空間給 b[3][1]!
所以,要先 b[3] = malloc(n);,才能讀寫 b[3][1]!(n > 1)(註:malloc 在 C++ 建議用 new)
在算b[2][1]時,是由 b[2]找到 b[2][0] 的位置,再加 1單位 找到 b[2][1]!
因為每個 b[0]、b[1]、b[2]、b[3]可以配置不同大小的東東,如:
代碼: |
for (i=0; i<4; i++) b[i] = malloc(sizeof(*b) * (i * i + 1)); /* C 和 C++ 在這裡不同! C 會自動轉換型別 (coercion, implicit type conversion) , C++一定要手動轉型 (cast, explicit type conversion)! 所以,C++ 要在 = 右邊放上 (int) ,C不用。*/ |
那,**c 呢?它等同於前述的 compiler 配給 a 或 b 本身的東東。That's all!
沒有任何其它空間配給 c[_] 或 c[_][_]!
(和 b 一樣,配置足夠空間後,給每個c[_]初值:對應到可用的空間,就可以用了。
沒做上述處理前,c[2][1] 在 compile 時是合法的!但執行時(runtime)會出問題!)
[] 和 * 至少還有一個差別,請參 http://tw.knowledge.yahoo.com/question/?qid=1607082407793 的最佳解答與意見
二維陣列的種類(二):差別
由上可知,雖然a, b, c 都是二級指位器,但至少有五大不同:
1. 配置法: initial 時的配置(前述)
2. 找法:執行時,找 x[_][_]的方法(前述)
3. 配置區:函數內宣告的變數(不管是不是陣列、幾維),用的 RAM 是 Stack。
其它方式的變數(全域(global)、用static 修飾、或是用動態配置(malloc()系 或 new))用的 RAM 是 Heap。
4. 最大 大小:
Stack 通常都很小:幾 K(Apple][ 是 0.25K ) 到幾 M(XP 好像是 4M);
Heap 就是接近整個 RAM,有的還會含 虛擬記憶體 (VM)。
5. 速度:有些電腦,Stack 會比 Heap 快一點!
(當然也要 compiler 有用那功能才會看到差別。)
(感謝 iseeyou 在討論中提供了一個例子!

這個差別就算有,也不大。
不過,Stack 幾乎不會用到 VM,Heap 就很有可能!
一旦用到 VM,所有的電腦都一樣,Heap 的速度就……

malloc 的上限 http://tw.knowledge.yahoo.com/question/question?qid=1406072517903
大二維動態配置應注意事項
強列不建議用上面二維陣列的種類(一)裡示範碼的寫法,去做大的二維動態配置!
速度是大陣列的重點!二維動態配置常用在大陣列上!
配置法錯誤,速度有明顯的差異!
上面的寫法至少有五個問題:
1. 初值化時的速度:所有有在研究/大量使用malloc 的都知道:malloc 有個致命傷:很慢!!!
不管在 DOS / Windows / Linux / Unix 都一樣!
2. 使用時的速度:每個第二維的陣列都存在不同的位置,
a. 陣列本身失去 locality 的加速性!
b. 不可用跨維計算位址!
3. 比較耗 RAM:每次 malloc/new,OS會用掉另一小塊 RAM來記得這塊 RAM 分配出去了!
這個小塊 RAM 是一般程式裡看不到的!
超大陣列就在怕 RAM 不夠用了,還讓 OS 吃掉寶貴的 RAM!

嫌 RAM 太快,想用 VM 來降速?

4. 用完要 free 時,free 到昏倒!而且,free 也不快!
5. 當 parallel 時,send/receive 明顯變慢!
所以,我建議
new/malloc 二次就好!因此,也只要 delete/free 二次就好!
一次是[ROW*COLUMN],一次是 *[ROW],再用個迴圈把*[ROW]依序指到[ROW*COLUMN]裡去!
如果要速度、陣列 Size 小於(約)2M,可以用
int P[大數]
或
int P[中數][中數]
去做,速度會比 動態 的做法快!
改天我有空再補這部份
陣列 是 const pointer
http://tw.knowledge.yahoo.com/question/question?qid=1008010406774
全站熱搜