Java與F#的并行程序處理對比
Azul System的Cliff Click博士是多核心JVM系統(tǒng)方面的專家,之前發(fā)表了一篇博文,首先比較了Java與C語言和C++的性能表現(xiàn),但同時也討論了C#和.NET。以下三個Cliffs博士的評論讓人十分感興趣:
在標題"Places where C/C++ beats Java for obvious reasons"下:
“值類型,例如復雜類型,在Java中需要一個類來支持”
"Value Types, such as a 'Complex' type require a full object in Java." - Dr Cliff Click
Cliff忘記提及的是.NET同樣提供值對象和比復數(shù)更加引人注意的humble hash table。
考慮一下以10,000,000個整數(shù)/單精度浮點數(shù) 填充hash表,這個任務(wù)可以使用Java來完成,如下:
- package hashtablebenchmark;
- import java.util.HashMap;
- public class Main {
- public static void main(String[] args) {
- int n = 10000000;
- for (int j=0; j<10; ++j) {
- long startTime = System.currentTimeMillis();
- HashMap hashtable = new HashMap(n);
- for(int i=1; i<=n; ++i) {
- hashtable.put(i, 1.0f / i);
- }
- System.out.println("m[100] = " + hashtable.get(100));
- long time = System.currentTimeMillis() - startTime;
- System.out.println("Took: " + time / 1e3 + "s");
- }
- }
- }
同樣的程序在F#中不僅僅代碼更短并且速度要快上17倍:
- let n = 10000000
- let m = System.Collections.Generic.Dictionary(n)
- for i=1 to n do
- m.[i] <- 1.0f / float32 i
- printf "m[100] = %f\n" m.[100]
特別值得提及的是,Java初始化花費6.967s、穩(wěn)態(tài)花費5.733s,而F#只用了0.414s。
實際上,F(xiàn)#通過這個測試后我們便想給它更大的工作量,而在這臺4GB內(nèi)存的機器上,Java不可能再做更多了。
在別處的評論,Cliff也這樣寫到Java:
“有非常好的多線程支持,并行程序設(shè)計在Java中很容易實現(xiàn)”
"Very Good Multi-Threading Support. Parallel programming is just easier in Java." - Dr Cliff Click
之后又有:
“并非我如此關(guān)注C#而是...我認為JIT編碼處理基本上比Java要慢”
"Not that I track C# all that closely but... I believe the JIT produces substantially slower code than Java" - Dr Cliff Click
允許我們在其他方面來證明,Computer Language Shootout軟包含了一個格式良好的spectral-norm測試,最快的Java解決方案是一個173行的并行程序。其實現(xiàn)用F#來寫只需要24行代碼:
- let A i j = 1.0 / float((i + j) * (i + j + 1) / 2 + i + 1)
- let inline mul A (u: _ []) (v: _ []) =
- System.Threading.Tasks.Parallel.For(0, v.Length, fun i ->
- let mutable vi = 0.0
- for j = 0 to v.Length - 1 do
- vi <- vi + A i j * u.[j]
- v.[i] <- vi) |> ignore
- let AtAu u v =
- let w = Array.create (Array.length u) 0.0
- mul (fun i j -> A i j) u w
- mul (fun i j -> A j i) w v
- do
- let n = 5500
- let u, v = Array.create n 1.0, Array.create n 0.0
- for i = 0 to 9 do
- AtAu u v
- AtAu v u
- let u, v = vector u, vector v
- printf "%0.9f\n" (sqrt(Vector.dot u v / Vector.dot v v))
在Java代碼中,大量的代碼都是用來實現(xiàn)并行化。與之相反的是,F(xiàn)#在處理并行化上只用了兩行代碼。可見,并行程序設(shè)計在Java中可不是那么easy。
Java串行程序初始花費了12.722s穩(wěn)態(tài)花費12.299s,而冷啟動的F#只用了12.18s。在8核 2xE5405 2.0GHz Xeon的機器上,Java并行程序初始化花費1.839s穩(wěn)態(tài)花費1.820s,而冷啟動的F#并行程序只用了1.60s。事實證明,Java在每一個測試中都表明CLR的JIT并不是“處理基本上比Java更慢”
***,Cliff并沒有提到其他兩個設(shè)計上(Java性能)的不足。首先,Java的泛型代碼導致性能大幅下降,由于它使用了許多不必要的裝箱操作。其次,JVM棧缺少尾部遞歸支持,這不僅僅對這個函數(shù)式編程的年代帶來越來越多的障礙,而且唯一的一般解決方案也比需要的慢上10倍。
英文連接:http://fsharpnews.blogspot.com/2010/05/java-vs-f.html
原文鏈接:http://www.oschina.net/news/26564/java-vs-f
【編輯推薦】