I have a situation where performance is extremely important. At the core of my algorithm there is a method that does some basic calculations with two double
primitives. This method is called over ten million times per run of the algorithm.
The code looks something like this;
public int compare(double xA, double xB, double yA, double yB);
double x = xA * xB;
double y = yA * yB;
double diff = x - y;
return (diff < 0.0 ? -1 : (diff > 0.0 ? 1 : 0));
}
The parameters xA
and yA
take their values from a set. This set can be tweaked in the code. I am seeing huge (approximately double) performance differences depending on the values I put into the set. It seems that if the set contains a 0.1
or a 0.3
, the performance takes a big hit. Keeping the set to just multiples of 0.5
gives the best performance.
Is the compiler optimising x * 0.5
as x >> 1
etc? Or is this because 0.1
cannot be defined in binary?
I'd like to understand this situation a bit better so that I can optimise this. I guess it might be quite a hard problem unless someone knows exactly how javac and the jvm (in our case hotspot) handles double multiplication.
Just a couple few ideas:
If values are multiple of 0.5, then there will be few significant bits in the mantissa,so it seems feasible that multiplication takes fewer cicles. Actually significant bits for multiplication doesn't seem to be an issue, since modern processors will take just two cycles for double (as explained in Floating point division vs floating point multiplication).
E.g. I figure that with 0.5 , 1 , 2, 4 , etc the mantissa will be all zeroes (first "1" is ommited for being implicit). For .75, 1.5, 3 etc, it will be a "1" in the m.s.b. followed by all zeroes. Whereas 0.1 would use all the significand precission to be represented, and even then have an small error.
About the result returned: Is there any problem with Math.signum()?. I mean, maybe this would do the same:
return Math.signum(x-y);
If precission is not paramount, you might consider using single precission (float). (though if that means you are going to be converting back and forth from double, then it may not be worth it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With