Java: implementazione fp a 32 bit di matematica.sqrt()


Il metodo standard Math.sqrt() sembra già abbastanza veloce in Java, ma ha lo svantaggio intrinseco che coinvolgerà sempre operazioni a 64 bit che non fanno altro che ridurre la velocità quando si tratta di valori float a 32 bit. È possibile fare meglio con un metodo personalizzato che utilizza un float come parametro, esegue solo operazioni a 32 bit e restituisce un float come risultato?

Ho visto:

Sqrt veloce in Java a scapito della precisione

E ha fatto poco più che rafforzare l'idea che la matematica.sqrt () è generalmente difficile da battere. Ho anche visto:

Http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi

Che mi ha mostrato un sacco di interessanti hack C++/ASM che sono semplicemente troppo ignorante per portare direttamente su Java. Anche se sqrt14 potrebbe essere interessante come parte di una chiamata JNI . . .

Ho anche guardato Apache Commons FastMath, ma sembra che la libreria sia predefinita allo standard Matematica.sqrt () quindi nessun aiuto lì. E poi c'è Yeppp!:

Http://www.yeppp.info /

Ma non mi sono ancora preoccupato di questo.

Author: Community, 2015-06-11

2 answers

Non hai bisogno di nulla per accelerare sqrt per i valori a 32 bit. HotSpot JVM lo fa automaticamente per te.

Il compilatore JIT è abbastanza intelligente da riconoscere il pattern f2d -> Math.sqrt() -> d2f e sostituirlo con un'istruzione CPU sqrtss più veloce invece di sqrtsd. La fonte.

Il parametro di riferimento:

@State(Scope.Benchmark)
public class Sqrt {
    double d = Math.random();
    float f = (float) d;

    @Benchmark
    public double sqrtD() {
        return Math.sqrt(d);
    }

    @Benchmark
    public float sqrtF() {
        return (float) Math.sqrt(f);
    }
}

E i risultati:

Benchmark    Mode  Cnt       Score      Error   Units
Sqrt.sqrtD  thrpt    5  145501,072 ± 2211,666  ops/ms
Sqrt.sqrtF  thrpt    5  223657,110 ± 2268,735  ops/ms
 5
Author: apangin, 2015-06-11 10:34:12

Come sembra di sapere JNI:

Basta scrivere un wrapper minimo per double sqrt(double) e float sqrt(float) dalla libreria standard di C math.h e confrontare le prestazioni.

Suggerimento: non sentirai alcuna differenza a meno che tu non faccia un sacco di rooting quadrato, e quindi il vantaggio in termini di prestazioni dell'uso delle istruzioni SIMD per eseguire più sqrt contemporaneamente dominerà molto probabilmente gli effetti. Avrai bisogno di ottenere una matrice allineata alla memoria dei valori in virgola mobile da Java, che può essere piuttosto difficile, se stai usando Java librerie standard.

 0
Author: Marcus Müller, 2015-06-11 09:13:00