Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Should I Use "sqrt(n)" or "pow(n,0.5f)"?

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Should I Use "sqrt(n)" or "pow(n,0.5f)"?
Kris Asick
Member #1,424
July 2001

Occasionally, I notice things I can't believe I hadn't before. One of them just now is that taking a number to the power of 0.5 results in the same answer as taking the square root of that number.

So my question is pretty simple: Which is the fastest for the CPU?

sqrt(n);

OR

pow(n,0.5f);

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Evert
Member #794
November 2000
avatar

Try both and use a profiler to find out.

My bet: sqrt(x) is faster than pow(x, 0.5) because there is a dedicated function for it (even if there wasn't one, sqrt(x) would be aliased to pow(x, 0.5) and therefore run at the same speed).

gnolam
Member #2,030
March 2002
avatar

Use sqrt() for code clarity if nothing else. If you mean a square root, write it like a regular square root - just like you'd usually write <math>\sqrt{x}</math> instead of <math>x^{\frac{1}{2}}</math>.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

bamccaig
Member #7,536
July 2006
avatar

Arthur Kalliokoski
Second in Command
February 2005
avatar

x86 has its own intrinsic sqrt function, which (at least at one time) was supposed to be faster than a division.

They all watch too much MSNBC... they get ideas.

Tobias Dammers
Member #2,604
August 2002
avatar

gnolam said:

Use sqrt() for code clarity if nothing else.

Seconded.
Unless this calculation needs to be done in a very time-critical part of your code, in which case you should first optimize your algorithms to avoid expensive operations where possible, then carefully profile to find out which performs better.
It may even differ between CPUs, who knows.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Evert
Member #794
November 2000
avatar

gnolam said:

just like you'd usually write \sqrt{x} instead of x^{\frac{1}{2}}

Funny, I tend to write the fractional exponent most of the time. It looks better if you have a very big expression under the root. I also deal with different fractional exponents and <math>x^{7/2}</math> looks cleaner than <math>\sqrt{x^7}</math> in most cases. Let alone <math>x^{4/3}</math> instead of <math>\sqrt[3]{x^4}</math>.

EDIT: but I always set it as <math>x^{1/2}</math>, never <math>x^\frac{1}{2}</math>.

Jonatan Hedborg
Member #4,886
July 2004
avatar

sqrt is probably a LOT faster than pow(n, 0.5f). Specific algorithms versus generic ones... I would not be surprised if sqrt beats pow by an order of magnitude or more. Do some testing on it.

Also, it's clearer.

-------
Sweden: Free from the shackles of Democracy since 2008-06-18!

gnolam
Member #2,030
March 2002
avatar

Evert said:

I also deal with different fractional exponents and <math>x^{7/2}</math> looks cleaner than <math>\sqrt{x^7}</math> in most cases. Let alone <math>x^{4/3}</math> instead of <math>\sqrt[3]{x^4}</math>.

That's why I added the "usually". :)
If 1/2 is a special case among other fractional exponents, I'd of course write it like the others. Likewise if there's multiple exponentiation involved (e.g. <math>(x^{1/2})^3</math>). But if it's a "natural" square root, the radical makes it instantly obvious what you're dealing with.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Karadoc ~~
Member #2,749
September 2002
avatar

I almost exclusively write square root as an exponent when I work with them on paper - mostly because it looks neater. For example, I find it difficult to get a neat looking square root sign on the bottom of a faction, or a neat square root over a long expression.

Never the less, I'd still use sqrt(x) rather than pow(x, 0.5) when I'm programming.

-----------

StevenVI
Member #562
July 2000
avatar

I found this intriguing, so I went ahead and wrote my own test for it.

The code:

#include <stdlib.h>
#include <math.h>
#include <limits.h>


int p(int p) { pow(p, 0.5); }
int s(int s) { sqrt(s); }

int main(int argc, char *argv[]) {
        int i;
        for(i=0; i<1231231231; i++) {
                int r = rand();
                s(r);
                p(r);
        }
}

The result from gprof:

  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 49.9      60.16    60.16 1231231231     0.00     0.00  p [2]
 44.2     113.45    53.29 1231231231     0.00     0.00  s [3]
  5.3     119.81     6.35                             main [1]
  1.3     121.33     1.52                             _gmon_start_ [4]

The self-seconds column is the important one here. I would conclude that there is hardly any difference.

(I too use fractional exponents, by the way.)

__________________________________________________
Skoobalon Software
[ Lander! v2.5 ] [ Zonic the Hog v1.1 ] [ Raid 2 v1.0 ]

Evert
Member #794
November 2000
avatar

That test is flawed: to do a meaningful test, you need to compile with optimisations switched on, but since the results are never used, the compiler can (and will) eliminate the calculations altogether.

Arthur Kalliokoski
Second in Command
February 2005
avatar

It'd also help if the calculations actually did useful work, so that any concurrency could be taken advantage of.

They all watch too much MSNBC... they get ideas.

torhu
Member #2,727
September 2002
avatar

Try something like this, compile with -O2 or -O3. You need one version for each function to test. Time it with the time command or something.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char *argv[]) {
        double acc = 0;
        int i;
        for(i=0; i<100000000; i++) {
                acc += sqrt(rand());
        }

        printf("%f\n", acc);
        return 0;
}

Oscar Giner
Member #2,207
April 2002
avatar

rand is not a fast function though. It may even be slower than sqrt so you're testing more rand than sqrt.

torhu
Member #2,727
September 2002
avatar

Could be, but the point is to see what happens if you replace sqrt(rand()) with pow(rand(), 0.5);

Oscar Giner
Member #2,207
April 2002
avatar

But that only allows you to know if one is faster than the other, but not by how much as Harry posted.

Evert
Member #794
November 2000
avatar

Just calculate sqrt(i) or the result of some simple function of i.

gillius
Member #119
April 2000

You also want to make sure the edge-case optimization is the same -- ideally you want the same input sets. It might make more sense to store the random numbers generated (to get around the 1 million array, you could make like a 100k array and loop it 10 times). That way you pass the same values to both.

I would agree with Evert's first reply, though. If pow cannot be faster than sqrt, because if there was a way of doing pow faster than sqrt, the library implementer would call pow from sqrt. Of course, I assume a world with all of the same hardware. It theoretically could be possible that an implementation of sqrt that is faster than pow on some hardware could be slower on another hardware; however, I would imagine that to be an unlikely scenario.

Gillius
Gillius's Programming -- http://gillius.org/

Kris Asick
Member #1,424
July 2001

Geeze... once again I've proven that all I have to do is say something and people will debate for hours! ::)

Since I only have to make the call 200 times a second, and because I wanted fine control over the shape of the curve, I decided to use pow() with a constant so that I can just change the constant if I feel the exponential curve is too shallow or too steep.

But, don't let that stop any of you from continuing to explore which is better for square roots. ;D

(Note to Mods: "proven" is missing from the spell check dictionary.)

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Arthur Kalliokoski
Second in Command
February 2005
avatar

Your original post lead us to believe the needed square root was time critical.

They all watch too much MSNBC... they get ideas.

Evert
Member #794
November 2000
avatar

Since I only have to make the call 200 times a second, and because I wanted fine control over the shape of the curve, I decided to use pow() with a constant so that I can just change the constant if I feel the exponential curve is too shallow or too steep.

But, don't let that stop any of you from continuing to explore which is better for square roots. ;D

That is a bit rich, coming from the guy who asked

So my question is pretty simple: Which is the fastest for the CPU?

sqrt(n);

OR

pow(n,0.5f);

Speedo
Member #9,783
May 2008

It may be implementation dependent, but at least on MSVC9 sqrt() appears to be significantly faster than pow(). I would generally advocate using sqrt() regardless just for readability.

Test:

#SelectExpand
1#include <cmath> 2#include <ctime> 3#include <iostream> 4 5int main( ) 6{ 7 const int loops = 10000000; 8 float f; 9 10 std::time_t start = std::clock( ); 11 12 for (int i = 0; i < loops; ++i) 13 f = std::sqrt(static_cast<float>(i)); 14 15 std::cout << std::clock( ) - start << std::endl; 16 std::cout << f << std::endl; 17 18 start = std::clock( ); 19 20 for (int i = 0; i < loops; ++i) 21 f = std::pow(static_cast<float>(i), 0.5f); 22 23 std::cout << std::clock( ) - start << std::endl; 24 std::cout << f << std::endl; 25 26 return 0; 27}

Average time across 10 tests:
sqrt: 249.6
pow: 967.3

Edit: Tests are with optimization.

Kris Asick
Member #1,424
July 2001

Evert said:

That is a bit rich, coming from the guy who asked

Maybe, but I was mostly just curious because it's not something I ever put any thought into and was wondering if someone else already knew. ;)

I think it's easy to forget with all the other problems which come up on this forum that not everyone has critical issues. If CPU time was a critical factor I would've tested this myself and never asked. :P

I'm still kinda surprised how many people responded to a question I thought was really simple and unimportant.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

BlackShark
Member #9,796
May 2008

Give this Square root function a go,

float SquareRoot(float number) {
    long i;
    float x, y;
    const float f = 1.5F;

    x = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;
    i  = 0x5f3759df - ( i >> 1 );  //Black magic mystery number
    y  = * ( float * ) &i;
    y  = y * ( f - ( x * y * y ) );
    y  = y * ( f - ( x * y * y ) );
    return number * y;
}

-BlackShark

 1   2 


Go to: