Re: [PATCH] lib/int_sqrt.c: Optimize square root function

From: Anshul Garg
Date: Thu Feb 05 2015 - 13:43:43 EST


On Thu, Feb 5, 2015 at 10:33 AM, Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, Feb 5, 2015 at 10:20 AM, Linus Torvalds
> <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
>>
>> Hmm. I did that too [..]
>
> Side note: one difference in our results (apart from possibly just CPU
> uarch details) is that my loop goes to 100M to make it easier to just
> time it. Which means that my load essentially had about three more
> iterations over nonzero data.
>
> Linus

I have also done the same testing on 100 million numbers.
Attaching source codes.

Below is the result ::

int_sqrt_old - current
int_sqrt_new - With proposed change

anshul@ubuntu:~/kernel_latest/sqrt$ time ./int_sqrt_old

real 0m41.895s
user 0m36.490s
sys 0m0.365s

anshul@ubuntu:~/kernel_latest/sqrt$ time ./int_sqrt_new

real 0m39.491s
user 0m36.495s
sys 0m0.338s


I have run this test on Intel(R) Core(TM) i3-4000M CPU @ 2.40GHz VMWare Machine.
Please check if i am doing anything wrong.

NOTE ::
I have not used gcc optimizations while compilation.
With O2 level optimization proposed solution is taking more time.
/*
* Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@xxxxxx>
*
* Based on the shift-and-subtract algorithm for computing integer
* square root from Guy L. Steele.
*/

#include <stdio.h>
/**
* int_sqrt - rough approximation to sqrt
* @x: integer of which to calculate the sqrt
*
* A very rough approximation to the sqrt() function.
*/
#define BITS_PER_LONG (8*sizeof(long))

unsigned long int_sqrt(unsigned long x)
{
unsigned long b, m, y = 0;

if (x <= 1)
return x;

m = 1UL << (BITS_PER_LONG - 2);
while (m != 0) {
b = y + m;
y >>= 1;

if (x >= b) {
x -= b;
y += m;
}
m >>= 2;
}

return y;
}

int main()
{
unsigned long n = 1;
for(;n<=100000000;++n)
int_sqrt(n);
return 0;
}
/*
* Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@xxxxxx>
*
* Based on the shift-and-subtract algorithm for computing integer
* square root from Guy L. Steele.
*/

#include <stdio.h>

#define BITS_PER_LONG (8*sizeof(long))

/**
* int_sqrt - rough approximation to sqrt
* @x: integer of which to calculate the sqrt
*
* A very rough approximation to the sqrt() function.
*/
unsigned long int_sqrt(unsigned long x)
{
unsigned long b, m, y = 0;

if (x <= 1)
return x;

m = 1UL << (BITS_PER_LONG - 2);

while(m > x )
m >>= 2;

while (m != 0) {
b = y + m;
y >>= 1;

if (x >= b) {
x -= b;
y += m;
}
m >>= 2;
}

return y;
}

int main()
{
unsigned long n = 1;
for(;n<=100000000;++n)
int_sqrt(n);
return 0;
}