I am currently trying to optimize some code where 50% of the time is spent in std::pow()
. I know that the exponent will always be a positive integer, and the base will always be a double in the interval (0, 1). For fun, I wrote a function:
inline double int_pow(double base, int exponent)
{
double out = 1.0;
for(int i = 0; i < exponent; i++)
{
out *= base;
}
return out;
}
I am compiling with:
> g++ fast-pow.cpp -O3 --std=c++11
I generated 100 million doubles between (0, 1) and compared the timings of (1) std::pow
(2) my homemade int_pow
function from above and (3) direct multiplication. Here's a sketch of my timing routine (this is a very quickly put-together test):
void time_me(int exp, size_t reps)
{
volatile double foo = 0.0;
double base = 0.0;
size_t i;
for (i = 0; i < reps; ++i)
{
base = ((double) rand() / (RAND_MAX)) + 1;
foo = pow(base, exp);
// foo = int_pow(base, exp);
// foo = base * base * base;
}
// check that the loop made it to the end
std::cout << foo << " " << i << std::endl;
}
int main()
{
std::clock_t start;
start = std::clock();
time_me(3, 1e8);
std::cout << "Time: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << std::endl;
return 0;
}
Here are the timings I've observed for various exponents:
- 0:
std::pow
0.71s,int_pow
0.77s - 2:
std::pow
1.31s,int_pow
0.80s, direct mult 0.86s - 3:
std::pow
6.9s (!!),int_pow
0.84s, direct mult 0.76s - 5: Similar to 3:
My Questions
So with this, my questions are:
- Why does the performance of
std::pow
appear to degrade so badly for powers greater than 2? - Is there an existing faster power function when the base or exponent types are known ahead of time?
- Is there something completely obvious I'm overlooking? I'm about to go through gut
std::pow
for the cases with known integer exponents, and would hate to have missed something completely trivial.
Thanks!!