Search code examples
javaperformancemath32-bit

Java: 32-bit fp implementation of Math.sqrt()


The standard Math.sqrt() method seems pretty fast in Java already, but it has the inherent drawback that it is always going to involve 64-bit operations which does nothing but reduce speed when dealing with 32-bit float values. Is it possible to do better with a custom method that uses a float as a parameter, performs 32-bit operations only, and returns a float as a result?

I saw:

Fast sqrt in Java at the expense of accuracy

and it did little more than reinforce the notion that Math.sqrt() is generally hard-to-beat. I also saw:

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

which showed me a bunch of interesting C++/ASM hacks that I am simply too ignorant to port directly to Java. Though sqrt14 might be interesting as a part of a JNI call . . .

I also looked at Apache Commons FastMath, but it looks like that library defaults to the standard Math.sqrt() so no help there. And then there's Yeppp!:

http://www.yeppp.info/

but I haven't bothered with that yet.


Solution

  • You need nothing to speed up sqrt for 32-bit values. HotSpot JVM does it automatically for you.

    JIT compiler is smart enough to recognize f2d -> Math.sqrt() -> d2f pattern and replace it with faster sqrtss CPU instruction instead of sqrtsd. The source.

    The benchmark:

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

    And the results:

    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