回答
通常情況下,最好的東西對於這樣的問題,搜索anwers時做的是看選用的是如何編譯成JVM字節碼:
multi = new int[50][50];
single = new int[2500];
這被翻譯成:
BIPUSH 50
BIPUSH 50
MULTIANEWARRAY int[][] 2
ASTORE 1
SIPUSH 2500
NEWARRAY T_INT
ASTORE 2
因此,如您所見,JVM已知道我們正在討論多維數組。
進一步保持它:
for (int i = 0; i < 50; ++i)
for (int j = 0; j < 50; ++j)
{
multi[i][j] = 20;
single[i*50+j] = 20;
}
這被翻譯(跳過週期)分爲:
ALOAD 1: multi
ILOAD 3: i
AALOAD
ILOAD 4: j
BIPUSH 20
IASTORE
ALOAD 2: single
ILOAD 3: i
BIPUSH 50
IMUL
ILOAD 4: j
IADD
BIPUSH 20
IASTORE
所以, 你可以看到, 多維陣列在內部處理中虛擬機, 無用的指令產生的開銷, 而使用單一的指令使用更多的指令,因爲抵消是手工計算。
我不認爲表現會是這樣的問題。
編輯:
我做了一些簡單的基準測試,看看是怎麼回事了這裏。 我選擇嘗試不同的例子: 線性讀取, 線性寫入, 和隨機存取。 時間以毫秒錶示(並使用System.nanoTime()
計算。 下面是結果:
線性寫
- 尺寸:100×100(10000) 多:5.786591 單:6.131748
- 尺寸:200×200(40000) 多:1.216366 單:0.782041
- 尺寸:500×500(250000) 多:7.177029 單:3.667017
- 尺寸:1000x100 0(1000000) 多:30.508131 單個:18.064592
- 尺寸:2000×2000(400萬) 多:185.3548 單個:155.590313
- 尺寸:5000x5000(25000000) 多:955.5299 單個:923.264417
- 尺寸:10000x10000(100000000) 多:4084.798753 單個:4015.448829
線性讀
- 尺寸:100×100(10000) 多:5.241338 單:5.135957
- 尺寸:200×200(40000) 多:0.080209 單:0.044371
- 尺寸:500×500(250000) 多:0.088742 單:0.084476
- 尺寸:1000×1000(1000000) 多:0.232095 單:0.167671
- 尺寸:2000×2000(400萬) 多:0.481683 單:0.33321
- 尺寸:5000x5000(25000000) 多:1.222339 單:0.828118 大小:10000x10000(100000000) 多:2.496302 單:1.650691
隨機讀
- 尺寸:100x100(10000) Multi:22.317393 Single:8.546134
- 尺寸:200×200(40000) 多:32.287669 單個:11.022383
- 尺寸:500×500(250000) 多:189.542751 單個:68.181343
- 尺寸:1000×1000(1000000) 多:1124.78609 單個:272.235584
- 尺寸:2000×2000(400萬) 多:6814.477101 單:1091.998395
- 尺寸:5000x5000(25000000) 多:50051.306239 單:7028。422262
隨機的一個有點誤導,因爲它爲多維數組生成2個隨機數,而對於單維(和PNRG可能消耗一些CPU)只產生一個隨機數。
請注意,我試圖讓JIT在同一循環的第20次運行後才通過基準測試工作。爲了完整我的Java VM如下:
Java版本 「1.6.0_17」 的Java(TM)SE運行時環境(建立1.6.0_17-B04) 的HotSpot的Java(TM)64位服務器VM(構建14.3-B01,混合模式)
總是很高興看到有人看到引擎蓋下的現實,而不是僅僅做出假設。如果可以的話,我會給你+100。 – 2010-03-25 03:38:51
在代碼發生故障時,JVM指令的數量無關緊要。重要的是代碼運行需要多少實際時間,這取決於地點,取消引用和內存使用情況。 – Gabe 2010-03-25 03:47:12
請更新隨機讀取基準,以便爲兩個版本生成2個隨機數。單陣列版本可能會更快,因爲需要更少的內存查找(隨機讀取會產生最多的緩存未命中),但在測量之前您永遠無法確定。 – 2010-03-25 15:52:11
如果你選擇後一種路線,那麼你將不得不爲每一個數組訪問執行算術。這將是一個痛苦和錯誤的傾向(除非你把它包裝在提供這種功能的類中)。
我不認爲在選擇平面數組時有任何(顯着的)優化(尤其是考慮到用於索引的算術)。與優化一樣,您需要執行一些測量並確定它是否真的值得。
好的,謝謝。我只打算使用三維數組,如果我遇到性能問題,請進行比較。 – Mikolan 2010-03-24 23:14:54
如果您使用多維數組,那麼您將不得不爲每個數組訪問執行多次內存訪問,這可能會讓我* buch *比一點算術慢。但是,是的,在你採取行動之前,你確實需要測量這種事情。 – 2010-03-25 14:20:59
使用第一變體(3維),因爲它是更容易理解並有機會少做一些邏輯錯誤(特別是如果你使用它的造型3維空間)
在當前的CPU,非緩存存儲器訪問是幾百倍算術(見this presentation和讀What every programmer should know about memory)慢。 a)選項將導致大約3次內存查找,而b)選項將導致大約1次內存查找。此外,CPU的預取算法也可能無法正常工作。所以b)選項在某些情況下可能會更快(這是一個熱點,並且陣列不適合CPU的緩存)。快多少? - 這取決於應用程序。
我個人會首先使用a)選項,因爲它會導致更簡單的代碼。如果剖析器顯示數組訪問是一個瓶頸,那麼我會將它轉換爲b)選項,以便有一對幫助器方法用於讀取和寫入數組值(這樣混亂的代碼將被限制爲這兩個方法)。
我做了一個比較3維int數組(「多」列)與等效1維int數組(「單」列)的基準。代碼是here和測試here。我使用JVM選項-server -Xmx3G -verbose:gc -XX:+PrintCompilation
(我從以下結果中刪除了調試輸出)將它運行在64位jdk1.6.0_18,Windows 7 x64,Core 2 Quad Q6600 @ 3.0 GHz,4 GB DDR2上。結果如下:
Out of 20 repeats, the minimum time in milliseconds is reported.
Array dimensions: 100x100x100 (1000000)
Multi Single
Seq Write 1 1
Seq Read 1 1
Random Read 99 90 (of which generating random numbers 59 ms)
Array dimensions: 200x200x200 (8000000)
Multi Single
Seq Write 14 13
Seq Read 11 8
Random Read 1482 1239 (of which generating random numbers 474 ms)
Array dimensions: 300x300x300 (27000000)
Multi Single
Seq Write 53 46
Seq Read 34 24
Random Read 5915 4418 (of which generating random numbers 1557 ms)
Array dimensions: 400x400x400 (64000000)
Multi Single
Seq Write 123 111
Seq Read 71 55
Random Read 16326 11144 (of which generating random numbers 3693 ms)
這表明1維陣列要快一些。雖然差異非常小,但對於99%的應用程序而言,它並不會引人注目。
我也做了一些測量,以便通過用preventOptimizingAway += x * y * z;
代替preventOptimizingAway += array.get(x, y, z);
來估計在Random Read基準中產生隨機數的開銷,並手動將測量結果添加到上述結果表中。生成隨機數佔隨機讀取基準測試總時間的1/3或更少,所以內存訪問如預期般支配基準。用4維和更多維的數組重複這個基準將會很有趣。可能會使速度差異更大,因爲多維數組的最高級別將適合CPU的高速緩存,並且只有其他級別需要查找內存。
- 1. [爪哇]環內聲明多維數組
- 2. 元素多維數組的,爪哇
- 3. 爪哇 - 維護對象
- 4. 爪哇 - 通過二維數組
- 5. 搜索在多維數組的話,爪哇
- 6. 爪哇 - 少見類型的多維數組
- 7. 爪哇:遞增地移動在一個二維數組元素
- 8. 多維數組與一維
- 9. 一維數組到多維數組
- 10. 爪哇 - 使用掃描成二維字符數組
- 11. Numpy:通過多維數組對多維數組排序
- 12. 使用索引對多維數組排序多維數組
- 13. 從多維數組中提取一維
- 14. 使多維數組一維沒有foreach
- 15. 打破多維數組爲一維
- 16. 使一維數組作爲多維
- 17. 多維數組到對象
- 18. Array_intersect對多維數組
- 19. 超對象多維數組
- 20. 多維數組對象
- 21. PHP多維數組對象
- 22. 對象多維數組
- 23. 轉換二維數組多維數組
- 24. 將多維數組合併到另一個多維數組中
- 25. 將多維數組插入到另一個多維數組中
- 26. 基於另一個多維數組排序多維數組?
- 27. php修復另一個多維數組的多維數組
- 28. 檢查多維數組存在另一個多維數組
- 29. PHP插入多維數組到另一個多維數組
- 30. 多維數組
另請參閱:http://stackoverflow.com/questions/2368761/performance-comparison-of-array-of-arrays-vs-multidimensional-array – polygenelubricants 2010-03-25 01:50:43