2013-07-01 70 views
23

我想知道,爲什麼Math.sin(double)委託給StrictMath.sin(double),當我在Reddit thread中發現問題時。所提到的代碼片段看起來像這樣(JDK 7u25):爲什麼Math.sin()委託給StrictMath.sin()?

Math.java

public static double sin(double a) { 
    return StrictMath.sin(a); // default impl. delegates to StrictMath 
} 

StrictMath.java

public static native double sin(double a); 

第二個聲明是native這是合理爲了我。的Math的文檔指出:鼓勵

代碼生成器使用特定於平臺的本機庫或者微處理器指令,如果有的話(...)

,問題是:ISN」 t實現了特定於平臺的本地庫是否足夠? JIT還可以知道關於該平臺的更多信息,而不是已安裝的JRE(請僅專注於這種情況)?換句話說,爲什麼不是Math.sin()本機已經?

+0

可能重複[java.lang.Math和java.lang.StrictMath有什麼區別?](http://stackoverflow.com/questions/4232231/whats-the-difference-between-java-lang-數學和Java的郎strictmath) –

+1

@Ruchira,你可以在我的問題看,我專注於東西比計算的精度不同(這是** **在文檔中描述) – emesx

回答

17

我會盡力包裹在一個崗位的整個討論..

一般來說,Math委託給StrictMath。很明顯,該電話可能是inlined,所以這不是性能問題。

StrictMath是由本地庫支持native方法final類。有人可能會認爲,這本地意味着最佳,但這並不一定必須是這種情況。翻翻StrictMath的javadoc可以閱讀以下內容:

(...)的一些在這個包的數值函數的定義,要求他們產生相同的結果一定公佈的算法。這些算法可以從衆所周知的網絡庫netlib中獲得,作爲「自由分佈式數學庫」包「fdlibm」。這些用C編程語言編寫的算法被理解爲遵循Java浮點運算規則的所有浮點運算。

我怎麼去理解這個文檔就是實施StrictMath本地庫中fdlibm庫,它是多平臺,並已知會產生可預見的結果方面實現。因爲它是多平臺的,它不能被預期爲每個平臺上最佳的實施和我認爲這就是一個聰明的JIT可以微調的地方的實際表現例如通過統計分析輸入範圍並相應地調整算法/實現。

更深的挖掘它迅速變成了實現,使本機庫備份StrictMath實際上使用fdlibm

StrictMath.c源中的OpenJDK 7看起來是這樣的:

#include "fdlibm.h" 
    ... 
    JNIEXPORT jdouble JNICALL 
    Java_java_lang_StrictMath_sin(JNIEnv *env, jclass unused, jdouble d) 
    { 
     return (jdouble) jsin((double)d); 
    } 

和正弦函數是在fdlibm/src/s_sin.c定義爲參照在幾個地方__kernel_sin函數直接從頭部FDLI自帶bm.h


雖然我暫時接受我自己的答案,我會當它出現很樂意接受更多的主管之一。

4

爲什麼Math.sin()委託給StrictMath.sin()?

JIT編譯器應該能夠內聯StrictMath.sin(a)調用。因此,爲Math.sin()案例創建一個額外的native方法並添加額外的JIT編譯器智能來優化調用序列,等等,沒有什麼意義。

鑑於此,您的異議真的歸結爲「優雅」問題。但「務實」的觀點更具有說服力:

  • 更少的本地調用,使JVM核心和JIT更容易維護,那麼脆弱,等等。

  • 如果沒有損壞,請不要修復它。

至少,這就是我想象 Java團隊會如何看待這一點。

+0

雖然是真實的,我希望得到不同的答案。我完全理解一個JIT如何優化上即時的代碼,但我不知道那是什麼在**特定於平臺的**優化方面做一個本地庫,編制了該平臺不能( *因爲這是文檔似乎建議*)。 – emesx

+0

這是你不需要這種能力的情況。但你可能會遇到其他情況。您可以嘗試深入瞭解JIT編譯器源代碼以查找特定於平臺的優化...:-) –

+1

「我希望得到一個不同的答案」 - 可悲的是,這往往是這樣。我同意斯蒂芬的觀點。雖然可能會出現平臺特定的JIT優化正在進行的情況,但看起來並不像這裏。 – selig

1

數學API允許其方法不嚴格,但性能更好的實現,但並不需要它,默認情況下,數學只是使用StrictMath IMPL。

4

該問題假定JVM實際運行委託代碼。在許多JVM上,它不會。對Math.sin()等的調用可能會被JIT用一些內部函數代碼(如果適用)透明地替換。這通常會以對最終用戶不可觀察的方式完成。這是JVM實施者,其中有趣的專長可能發生(即使該方法不標記爲母語)的共同伎倆。

注意然而,大多數平臺不能在爲罪單一處理器指令簡單地丟棄由於適當的輸入範圍(例如,參見:Intel discussion)。

+0

我會再次解釋我的問題:'StrictMath'是本地的,因此它根據定義使用了一些特定於平臺的低級庫。'Math'默認授予'StrictMath'(顯然這個調用可以被優化掉)指出,代表團**應該**替換爲**特定於平臺的**代碼。 JIT可以做什麼更具特定平臺的特定平臺? – emesx

+0

所以StringMath基本上是fdlibm本地代碼的傳遞,它非常與平臺無關,但可以預測答案。我知道你知道:-)平臺可以用數學代碼代替少量ULP分歧的代碼。它是如何被物理替換的,取決於JIT(或者類文件加載器),但是要給出一個真實世界的例子,可以(對於某些特定的輸入數字範圍)更直接地使用fsin指令。如果JIT可以證明(通過實時程序分析)輸入總是在安全範圍內,那麼它可以做到這一點,並提供巨大的加速。 –

+0

嘿,這是在某個地方。 +1指出'fdlibm' – emesx

相關問題