PS,我剛打完才發現我舉的例子中A是一維陣列,B是三維陣列,跟你原文相反...
※ 引述《iohan (iohan)》之銘言:
: 假設
: integer A(10,10,10)
: integer B(1000)
: 結構上看起來用的記憶體要一樣
: 但是我聽到有種說法是A使用的記憶體會比B還來的大!?
: 實際上是???
: 另外就是B的元素在記憶體上的分布是連續的這點不用質疑
: 那麼A呢??
也是連續的阿
假設B陣列是2*2*2的大小
那B陣列在記憶體裡的排列順序,以FORTRAN來說就是
B(1,1,1)、B(2,1,1)、B(1,2,1)、B(2,2,1)、B(1,1,2)、B(2,1,2)、B(1,2,2)、B(2,2,2)
至於使用的記憶體大小,我不太確定
至少在儲存陣列內的元素值所占用的記憶體大小是一樣的
但是有聽說陣列會另外儲存陣列維度上下限的值
所以DEBUGER才能檢查出是否有呼叫到超出當初陣列宣告時大小的陣列元素
一維陣列只要記錄一個方向的上下限,以A陣列來講就是紀錄1跟1000兩個數字
三維陣列要記錄三個方向的上下限,以B來講就是紀錄1、10、1、10、1、10六個數字
所以說三維陣列用到的記憶體會比一維陣列大一些
不過這點我是真的很不確定,只是聽說的
因為實際上DEGUGER檢查程式裡是否有呼叫到超出陣列大小的元素的功能是可以關掉的..
而且不同語言的可能作法也不同
: A(i,j,k)
: 書上說按照 i -> j -> k 的順序下去讀是連續的
: 但是聽到上面第一種的說法害我開始懷疑B的連續性...
: 假如真的是連續的
: 那麼A從1讀到1000
: 跟B從(1,1,1)讀到(10,10,10)
: 速度上會有差?? ( 我在實際應用上的矩陣B可能是300*300*300
我自己認為還是有差的
因為所謂的陣列,其實只是一個指標而已
這個指標紀錄了陣列第一個元素在電腦記憶體裡的位址
我們呼叫陣列裡某個元素時,電腦只是根據這個陣列第一個元素的記憶體位址,
去計算出我們呼叫的元素在哪個記憶體位址裡,再去該記憶體位址取值
譬如你舉的例子,A是大小1000的一維陣列,B是大小10*10*10的三維陣列
對電腦而言,A這個變數,他記錄的是A(1)在記憶體裡的位址
B這個變數,他紀錄的則是B(1,1,1)在記憶體裡的位址
電腦要呼叫A(10)的值,他必須去計算A(10)所在的記憶體位址跟A(1)之間的關係
找到A(10)的記憶體位址,才能取出該記憶體位址的值,也就是A(10)的值
譬如如果我們同樣呼叫兩個陣列第一個元素所在位址的後面第500個元素
在A陣列就是A(500)的值,B陣列就是B(10,10,5)這個元素的值
理論上電腦一開始並不會知道A(500)跟B(10,10,5)都是陣列的第500個元素
那電腦在呼叫A(500)時,
因為電腦只記錄A(1)的位址,所以為了要得知A(500)所在的記憶體位址
他必須要做計算:A(500)所在記憶體位址 = A(1)記憶體位址 + 500 - 1
也就是一個加號的計算跟一個減法
而電腦要得知B(10,10,5)的記憶體位址,他必須要做計算:
B(10,10,5)所在記憶體位址 = B(1,1,1)記憶體位址 + (5-1)*100 + (10-1)*10 + (10-1)
他必須要做2個乘法、3個加法、3個減法的計算,才能取得B(10,10,5)的值
在評估計算速度時,
為了簡化,我們通常會假設乘/除速度遠遠大於加減,所以只考慮乘/除的計算
因此可以很明顯看出,明明都是呼叫第500個元素的值,
三維陣列B所需要的時間會比一維陣列A多
因此理論上三維陣列的呼叫會比一維陣列慢
這是我自己的見解,若有誤,還請其他版友糾正
: 補個計概問題
: 請問一下電腦在執行指令時
: 不同的動作之間的速度比大概是怎麼樣的一個情況呢?
: ex.
: 浮點相乘: xxx Hz / s
: 浮點相除: ooo Hz / s
: 邏輯判斷: !!! Hz / s
: 讀記憶體: ??? Hz / s
: 寫記憶體: @@@ Hz / s
: 掃記憶體: ... Hz / s