Boost logo

Boost Users :

Subject: [Boost-users] [math][special_functions] Why is cbrt(x) slower than pow(x, 1/3)?
From: Tim Odenthal (Tim.Odenthal_at_[hidden])
Date: 2010-01-13 05:36:09


Hi!

For a (cell) simulation code I have to calculate lots of cubic roots in every
timestep. So I tried to improve performance on my first guess, namely pow(x,
1/3) using boost::math::cbrt(). To my astonishment, this is much slower than
the original code. I wrote a small test program to check this claim; compiling
with g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1 (-O3) on a Intel Core i7 CPU I get the
following timings (averaging the time over 10 trials):
average time to compute 5000000 roots with pow(): 0.603 s.
average time to compute 5000000 roots with boost::cbrt(): 1.087 s.
average time to compute 5000000 roots with improved boost::cbrt(): 1.015 s.
average time to compute 5000000 roots with exp(1/3*log()): 0.541 s.

My "improved" version allows giving the boost::math::cbrt() method a first
guess instead of taking just the value of the number whose root is to be
calculated.

Actually, the function I called in this instance 5000000 times does a bit
more than just calculating the root; I want to calculate the radii of to
spheres which overlap so, that their combined volume is equal to the volume of
a "mother sphere":

 /**
 * @brief calculates the radius of a daughter cell during symmetric division,
 * assuming the volume of the mother cell is conserved.
 *
 * @param MotherRadius radius of mother cell before division
 * @param Overlap of the two daughter cells, i.e. radius of daughter -
 * distance from center of daughter to middle-plane of
 * both cells
 *
 * @return for positive overlap returns positive radius, for negative overlap
 * negative radius
 **/
double daughterRadiusfOver( double MotherRadius, double Overlap) {
// r = 1/2 (2 sqrt(R^6-h^3 R^3)-h^3+2 R^3)^(1/3)+h^2/(2 (2 sqrt(R^6-h^3 R^3)-
h^3+2 R^3)^(1/3))
        double O3 = Overlap*Overlap*Overlap;
        double M3 = MotherRadius*MotherRadius*MotherRadius;

        double step1 = pow(-O3 + 2*sqrt(-O3*M3 + M3*M3) + 2*M3,1.0/3.0);//<-- CUBIC
ROOT HERE!!! Change to:
// double step1 = boost::math::cbrt(-O3 + 2*sqrt(-O3*M3 + M3*M3) + 2*M3);

        if ( Overlap < 0 ){
                cerr << "Warning in daughterRadiusfOver: Negative overlap given!" <<endl;
                return -(step1 + Overlap*Overlap/step1)*0.5;
        } else {
                return (step1 + Overlap*Overlap/step1)*0.5;
        }
}

Why is boost::math::cbrt() no improvement for me - or am I using it the wrong
way? For which cases might it be an improvement, or why is it in the library?
It's funny, but I found that std::exp(1/3*std::log(x)) is so far the fastest
way...

Thanks in advance
Tim


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net