2010-02-27 72 views
11

我的問題是關於Java與編譯代碼的性能,例如高性能數值應用程序中的C++/fortran/assembly。 我知道這是有爭議的話題,但我正在尋找具體的答案/例子。也社區維基。我之前曾問過類似的問題,但我想我把它放在一邊,並沒有得到我正在尋找的答案。雙精度矩陣矩陣乘法,通常稱爲blas庫中的dgemm,能夠實現近100%的CPU峯值性能(以每秒浮動操作爲單位)。
有幾個因素,其允許實現這一性能:高性能應用程序中的C/C++與Java/C#

  • 緩存阻擋,以達到最大的存儲器局部性

  • 循環展開以減少控制開銷

  • 矢量指令,諸如SSE

  • 內存預取

  • 保證沒有存儲器別名

我已經看到大量使用裝配基準,C++,FORTRAN,阿特拉斯,賣主BLAS(典型情況下是尺寸512和上面的矩陣)。另一方面,我聽說像Java這樣的原則字節編譯語言/實現可以像機器編譯語言一樣快或幾乎一樣快。但是我還沒有看到明確的基準表明它是如此。相反,從我自己的研究看來,字節編譯語言要慢得多。

對於Java/C#你有很好的矩陣矩陣乘法基準嗎? 做即時編譯器(實際的實現,而不是假設)能夠產生滿足我列出的點的指令嗎?

由於

與性能有關的: 每個CPU具有峯值性能,這取決於指令處理器可以每秒執行次數。例如,現代2 GHz的英特爾CPU可實現80億次雙精度加/乘一秒,從而實現8 gflops峯值性能。矩陣乘法是一種能夠在每秒操作次數方面達到近乎完整性能的算法之一,主要原因是計算超過內存操作的比率較高。(N^3/N^2)。數字我感興趣的訂單N > 500

關於實現:更高級別的細節(如阻塞)在源代碼級完成。較低級別的優化是由編譯器處理的,可能與編譯器提示有關對齊/別名。字節編譯的實現也可以使用塊方法編寫,所以原則上源代碼體面實現的細節將非常相似。

+0

我可以用Java編寫代碼,利用100%的CPU - 即使沒有做任何有意義的事情;-)我想我明白你的意思,但你的措辭有點含糊。 – 2010-02-27 21:09:58

+0

對我來說還是不太清楚......你的意思是有某種「理想」,它指出對於給定的CPU架構,最好的可以想象的數值性能是如此這般,這就是你所說的100%?是否會有像MFLOPS這樣的具體措施?我不是這方面的專家。 – 2010-02-27 21:16:23

+0

我沒有投票結束這篇文章(甚至沒有權利)。我覺得它很有趣,只是試圖給你反饋,澄清你的帖子。 – 2010-02-27 21:18:58

回答

0
+2

據我所知,它不使用SSE指令來向量化代碼,.NET CLR也沒有。單聲道確實有一些結構(矢量和矩陣),它們被JIT編譯器專門處理,並轉化爲矢量化代碼。 – JulianR 2010-02-27 21:21:18

+0

@JR這也是我的印象 – Anycorn 2010-02-27 21:55:39

1

所有因素您指定由手動內存/代碼優化您的具體任務可能完成。但是,JIT編譯器沒有足夠的關於您的域的信息,以便您手動完成代碼優化,並且只能應用一般優化規則。因此,它會慢一些的是C/C++矩陣操作代碼(但可以利用CPU的100%,如果希望:)

+0

是真的。但矢量化,鋸齒問題經常由編譯器處理。此外,循環展開一些我期望編譯器做的事情。高速緩存訪​​問在編譯語言中非常簡單,但字節編譯語言如何處理它呢? – Anycorn 2010-02-27 21:59:02

+0

@aaa:JIT引擎/編譯器負責處理該問題。 – LiraNuna 2010-02-27 22:42:42

2

的比較VC++/.NET 3.5 /單聲道2.2的純矩陣乘法場景:

http://img237.imageshack.us/img237/2788/resultse.png Source

單用Mono.Simd走一段很長的路要走朝着縮小與手工優化的C++這裏的性能差距,但C++版本依然清晰最快的。但是Mono現在已經在2.6了,可能會更接近我期望的是,如果.NET有了Mono.Simd之類的東西,它可能會非常有競爭力,因爲.NET和順序C++在這裏沒有太大的區別。

+0

謝謝。兩個SIMD實現之間有什麼區別?看起來與內存有關的數據? – Anycorn 2010-02-27 22:35:10

+1

說到C++中的SSE,我建議你也比較GCC 4.4,只是爲了完整性,因爲MSVC的SSE代碼生成非常可怕(參見http://www.liranuna.com/sse-intrinsics-optimizations-in-popular-編譯器/詳情)。 – LiraNuna 2010-02-27 22:36:37

0

java無法在矩陣乘法中與c競爭,原因之一是它會檢查每個數組的訪問權限是否超出數組邊界。進一步的java數學很慢,它不使用處理器sin(),cos()。