2015-03-23 9 views
5

Ich versuche, die Leistung von pow(x,2.0) und pow(x,2.0000001) zu vergleichen und ich dachte, dass 2.0 wäre viel schneller, aber sie sind mit der gleichen Geschwindigkeit. Ich habe sogar JIT-Optimierungen entfernt, indem ich jar mit -Xint Parameter ausgeführt habe.Java Math.pow (x, 2.0) vs Math.pow (x, 2.0000001) Leistung

Irgendeine Idee warum ist das bitte? Vielen Dank!

+1

Die Implementierung ist frei, eine bedingte Verzweigung für spezielle Fälle auszugeben oder alle Fälle mit demselben Code zu implementieren. Alles, was zählt, ist das Ergebnis. Es gibt keine Garantien für die Ausführungszeit. (Nicht das, wenn Sie nicht vorsichtig sind, würden Sie sie sogar sehen, wenn sie dort sind). –

+0

Warum erwarten Sie einen Leistungsschub? Die Art beider Parameter ist "doppelt". –

+0

Weil es nur eine magische Implementierung verwendet, die auf alle Doubles spezialisiert ist; Es wird keine spezielle Magie für Integer-Potenzen verwendet. Wenn Sie nur die Multiplikation direkt verwenden ('x * x'), erhalten Sie bessere Ergebnisse. –

Antwort

10

Trotz der unfairen Downvotes macht die Frage viel Sinn, da sie den echten JVM-Bug aufdeckt.

Wenn Sie Oracle JDK ausführen, variiert die Leistung von Math.pow(x, 2.0) zwischen JVM-Versionen stark.

  • Vor JDK 7u40 Math.pow verwendeten Software-Implementierung, das heißt es einfach __ieee754_pow Funktion aufgerufen, die den Betrieb in Software emuliert. Es war ziemlich langsam, aber es hatte einen speziellen Fall für y == 2.
  • Seit JDK 7u40 Math.pow wurde eine JVM intrinsisch, die von der JIT in FPU Anweisungen übersetzt wurde. Mit dieser Optimierung wurde jedoch der Spezialfall verloren, was zu einer Leistungsregression für y == 2 führte, siehe bug JDK-8029302.
  • Diese Leistungsregression wurde in JDK 8u25 und kommenden 7u80 behoben. Seit JDK 8u25 Math.pow arbeitet schnell genug für alle Werte, aber extrem schnell für y == 2. Siehe related question.

P.S. Die ungefähre Zeit in Sekunden für 100M Aufrufe von Math.pow auf meinem Rechner mit verschiedenen Versionen von JDK.

   Math.pow(x, 2.0) Math.pow(x, 2.0000001) 
JDK 7u25   3.0    30.4 
JDK 7u40   11.1    11.1 
JDK 8u40   0.1    11.1  
+1

Wenn Sie "Java-Implementierung" sagen, meinen Sie eigentlich eine native Methode, richtig? –

+1

Zitat aus dem verknüpften JDK-Fehler: 'Using" -XX: + UnlockDiagnosticVMOptions -XX: + PrintIntrinsics "zeigt die intrinsische Implementierung wird in beiden Fällen verwendet. So war die tatsächliche Änderung nur in der intrinsischen selbst, nicht in der Tatsache, dass ein intrinsisch wurde eingeführt. –

+2

@MarkoTopolnik Nun, es war eine ziemlich dumme intrinsische. Ich meine, es ist nicht durch alle [JNI-Sachen] gekrochen (http://stackoverflow.com/a/24747484/3448419) (in diesem Sinne war es ein * "intrinsic" *), aber es musste trotzdem ein natives machen Rufen Sie die Emulationsfunktion auf.In JDK7u40 wurde es zu einem * "echten intrinsischen" *, d. H. Die Implementierung wurde in Assembly geschrieben und in den Aufrufer eingegliedert. Ich habe die Antwort präzisiert. Danke für die Überprüfung :) – apangin

Verwandte Themen