Java: implémentation fp 32 bits de Math.sqrt()


La méthode standard Math.sqrt() semble déjà assez rapide en Java, mais elle a l'inconvénient inhérent qu'elle impliquera toujours des opérations 64 bits qui ne font que réduire la vitesse lorsqu'il s'agit de valeurs 32 bits float. Est-il possible de faire mieux avec une méthode personnalisée qui utilise un float comme paramètre, effectue des opérations 32 bits uniquement et renvoie un float en conséquence?

J'ai vu:

Rapide sqrt en Java au détriment de la précision

Et il a fait peu plus que renforcer la notion que les mathématiques.sqrt() est généralement difficile à battre. J'ai aussi vu:

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

Qui m'a montré un tas de hacks C++/ASM intéressants que je suis tout simplement trop ignorant pour porter directement vers Java. Bien que sqrt14 puisse être intéressant dans le cadre d'un appel JNI . . .

J'ai également regardé Apache Commons FastMath, mais il semble que cette bibliothèque soit par défaut la norme Mathématique.sqrt () donc pas d'aide là-bas. Et puis il y a Yeppp!:

Http://www.yeppp.info/

Mais je ne me suis pas encore soucié de cela.

Author: Community, 2015-06-11

2 answers

Vous n'avez besoin de rien pour accélérer sqrt pour les valeurs 32 bits. HotSpot JVM le fait automatiquement pour vous.

Le compilateur JIT est assez intelligent pour reconnaître f2d -> Math.sqrt() -> d2f pattern et le remplacer par une instruction CPU sqrtss plus rapide au lieu de sqrtsd. La source.

La référence:

@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);
    }
}

, Et les résultats:

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

Comme vous semblez le savoir JNI:

Il suffit d'écrire un wrapper minimal pour double sqrt(double) et float sqrt(float) à partir de la bibliothèque standard de C math.h et de comparer les performances.

Astuce: vous ne sentirez pas de différence à moins de faire beaucoup d'enracinement carré, puis l'avantage de performance d'utiliser les instructions SIMD pour faire plusieurs sqrts à la fois dominera très probablement les effets. Vous devrez obtenir un tableau aligné en mémoire des valeurs à virgule flottante de Java, ce qui peut être assez difficile, si vous utilisez Java bibliothèques standard.

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