2010-11-13 70 views
4

我在我的項目中使用了Java,它進行了大量的數學計算。在項目的下一次迭代中,將會添加更多的計算。從我對Java的知識中,我懷疑這會導致性能問題。將繁重的計算委託給像Fortran或C這樣的低級語言是明智的決定嗎?我可以通過本機調用來與低級語言進行通信。一旦Fortran或C執行計算,Java將採取控制。 性能會更好嗎?關於Java中的重數學計算的問題

回答

8

小心不要低估現代Java虛擬機。第一代速度非常慢,特別是在浮點運算上,但現代的速度確實非常快。

話雖如此,其他選擇可能會更快。

可以肯定,你應該運行一些基準測試。不要以爲其中一個會比另一個更快,得到一些具體的性能指標並在此基礎上做出決定。

另外考慮一個「原生」解決方案的額外性能(如果有的話)是否值得寫入它並整合它的額外麻煩。

+0

你說得對,本機代碼會花費額外的時間編碼和集成。目前計算需要12分鐘,添加新計算可能需要14分鐘。我的目標是把它降到8-9分鐘。 – Sid 2010-11-13 11:37:56

+4

另外請注意,如果你在JNI中複製數據,那麼這裏還有一個重大的發現。我參與過的大量數字代碼也涉及大量數據集,所以IO受限(通過CPU和內存之間的路徑)而不是CPU受限制,並且混合使用Java和本機代碼會使情況變得更糟。 – 2010-11-13 12:23:26

1

這取決於兩個因素:

  1. 你應該記住,JNI調用需要一定費用。如果可以將整個計算結果轉換爲C,那麼開銷可能變得微不足道,並且您可能會獲得一些性能。否則,如果你要在C和Java之間來回切換,你不會有很大的提高性能的機會。
  2. 假設你有一個函數f()來計算。您應該首先確定從C獲得的性能是否優於Java。我隱約記得一些基準測試C和Java的文章,它們實際上聲稱Java在數學計算方面做得更好。但無論如何,我會對兩者進行基準測試 - 至少是其中的一部分。
+0

我的想法是將所有計算移到C或Fortran以避免多個本地調用調用。 – Sid 2010-11-13 11:40:00

0

我會建議等着瞧...按照通常的方式用Java實現,然後衡量性能,是好的,可接受的還是不好的?

由於Skaffman甾體抗炎藥現代人的JVM具有高性能和感謝JIT編譯器他們在許多情況下比本地C.

This article顯示Java和C計算之間的一些比較,它也是一個例子使用最新的JVM版本是一個不錯的主意。

+0

我測量過的表現並不是很好。目前需要12分鐘才能完成計算。我使用了一些多線程。我需要把它降到8分鐘。 – Sid 2010-11-13 11:39:11

+0

-1,除非您編輯答案以包含至少一個同等評審的重數字Java代碼示例,其速度明顯快於C.通常,等同的Java代碼最好保持得相當好,而Java *系統通常會以更快的速度結束花更少的時間修復錯誤並有更多時間進行分析。 – 2010-11-13 11:44:32

+0

添加鏈接。有很多類似的文章和基準,有人會說C更快,有些人會說相反。我的主要觀點是,Java有一個緩慢的聲譽,現在它不是真的,因爲它通常基於10年前JVM的表現。 – Uhlen 2010-11-13 12:12:32

6

Java中的整數和浮點數學運算直接傳遞給硬件,原則上計算速度不會低於C或FORTRAN。像超驗函數(例如sin(),sqrt(),,log()等等)的庫例程實際上是用C實現的,所以再次沒有理由去查看其他庫。

我希望你的問題給我們提供了一些信息。你提到有很多計算正在進行,這就是數字計算。但是你不會告訴我們這些數字是如何組織和訪問的。這可能是有趣和有用的信息。如果您使用複雜的對象結構來保存數據,訪問這些結構將需要時間。如果你的結果創建新的對象,那也很昂貴。如果你使用數組,那些也是對象。Java中的多維數組是數組的數組,並且通過多維索引可能會解析爲比其他語言更慢的對象引用。雖然我沒有基準來證明它,但我懷疑用一維數組和一些「手動」索引計算替代多維數組可能會更好。當然,使用固定大小的數組可能會更好,可能會有一些鬆散的尺寸,而不是爲每次計算創建和丟棄新數組。最後,許多面向對象的技巧讓你的程序結構更「優雅」和「靈活」,往往會引入大量不必要的面向對象,伴隨着服務員的減速。原始但簡單通常更快。

一個非常簡單的優化可能是簡單地使用JVM的-server選項(如果有的話),以獲得更多預編譯的好處,如果您還沒有這樣做。

然而,在你盲目地重新設計你的程序之前,第二其他人的建議是你對你的計算進行剖析。在令人驚訝的地方可能會遇到瓶頸。

3

您可以考慮使用並行算法。它可能會或可能不適用於你的情況,但想到指出它。

+1

這是一個很好的建議,我希望我能想到它。如果OP的盒子中有2個或更多的CPU核心,並且任務可以被分割成並行任務,他幾乎可以直接將其計算時間減少(幾乎)2或更多,而不會顯着改變他的程序或使用外部的外語代碼。 – 2010-11-13 12:56:00

1

你也應該玩各種VM參數。以服務器模式運行程序,這樣JIT將生成更好的代碼,使用不同的垃圾收集器進行實驗,打開逃逸分析(可能更適合使用JDK 7)。

This paper可能會幫助您調整程序以使用最好的JVM。

如果您決定選擇本機路徑,請使用JNA,這樣會更容易,尤其是如果您的所有計算都在一次方法調用中。

1

到目前爲止所有的評論都非常好。我同意本地代碼應該是最後一步。

並行化是值得研究的。

所以會使用另一種算法,這取決於你在做什麼。

沒有人建議您對代碼進行簡介以找出所花費的時間。在開始任何修改之前,我會獲得一些數據以確切瞭解正在做什麼和在哪裏。它會比猜測更好地指導你的決定。