Tuesday, July 23, 2013

Python vs Perl vs Lua - speed comparison. Part 2

As far as people show interest in this topic I decided to perform an additional measurement to the one I performed in Part 1.

This time I wanted to compare floating point numbers operations performance because my good friend Anonymous worried about it. He said that I shouldn't have abused lua interpreter with basic arithmetic operations on integers because it's not good at it. He said that I should have tried floating points numbers instead to let lua interpreter shine. I was a bit skeptic about it to be honest but Anonymous's logic was sound.

To perform the test I decided to integrate an exponent from 0 to 1. This is not a really useful calculation I must confess but it offers lots and lots of floating point numbers calculations and its result is very easy to prove because it is known to be equal to e-1. I've also added a plain C implementation for the comparison

To calculate the exponent function I take first 100 terms of the Taylor series and all interpreters should operate with double precision at least because floats would be overflown by factorials.

Implementations are trivial but I put it here anyway so that everyone could repeat the tests if needed:

Perl:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
alex@thinkpad:~/projects$ cat speedcompar/exp.pl
#!/usr/bin/env perl
 
$explim = 100;
$step = 0.000001;
 
sub myexp
{
  my $i;
  my $sum = 0.0;
  my $fact = 1.0;
  my $x = 1.0;
  
  for ($i = 1; $i<=$explim; $i++) {
    $fact*= $i;
    $x*= $_[0];
    $sum+= $x/$fact;
  }
  return $sum+1.0;
}
 
sub integrate
{
  my $min = $_[0];
  my $max = $_[1];
  my $sum = 0.0;
 
  while ($min<$max) {
    $sum+= myexp($min)*$step;
    $min+=$step;
  }
 
  return $sum;
}
 
print "exponent( 1.0)=".myexp(1.0)."\n";
print "integral(0..1)=".integrate(0.0,1.0)."\n";

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
alex@thinkpad:~/projects$ cat speedcompar/exp.py
#!/usr/bin/env python
 
explimit=100
step=0.000001
 
def myexp(val):
  sum = 0.0
  fact = 1.0
  x = 1.0
 
  for i in range(1, explimit):
    fact = fact * i
    x = x * val
    sum = sum + x/fact
 
  return sum + 1.0
 
def integrate(min, max):
  sum = 0.0
 
  while min<max:
    sum = sum + myexp(min)*step
    min = min + step
 
  return sum
 
 
print "exponent( 1.0)=%s" % (myexp(1.0))
print "integral(0..1)=%s" % (integrate(0.0,1.0))

Lua:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
alex@thinkpad:~/projects$ cat speedcompar/exp.lua
#!/usr/bin/env lua
 
explim = 100
step = 0.000001
 
function myexp(val)
  local sum = 0.0
  local fact = 1.0
  local x = 1.0
  local i
 
  for i = 1, explim, 1 do
    fact = fact * i
    x = x * val
    sum = sum + x/fact
  end
 
  return sum + 1.0
end
 
function integrate(min,max)
  local sum = 0.0
 
  while min < max do
    sum = sum + myexp(min)*step
    min = min + step
  end
  return sum
end
 
print ("exponent( 1.0)=" .. myexp(1.0))
print ("integral(0..1)=" .. integrate(0.0,1.0))

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
alex@thinkpad:~/projects$ cat speedcompar/exp.c
#include <stdio.h>
 
int explimit = 100;
double step = 0.000001;
 
double myexp(double val)
{
  int i;
  double sum = 0.0;
  double x = 1.0;
  double fact = 1.0;
 
  for (i=1;i<=explimit;++i)
  {
    fact*=i;
    x*=val;
    sum+=x/fact;
  }
  return sum + 1.0;
}
double integrate(double min, double max)
{
  double sum = 0.0;
   
  while (min<max)
  {
    sum+=myexp(min)*step;
    min+=step;
  }
  return sum;
}
 
int main(int argc, char** argv)
{
  printf("exponent( 1.0)=%f\n", myexp(1.0));
  printf("integral(0..1)=%f\n", integrate(0.0,1.0));
}

And here are the results of the test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
alex@thinkpad:~/projects$ time speedcompar/exp.bin
exponent( 1.0)=2.718282
integral(0..1)=1.718281
 
real 0m0.951s
user 0m0.948s
sys 0m0.000s
 
 
alex@thinkpad:~/projects$ time speedcompar/exp.lua
exponent( 1.0)=2.718281828459
integral(0..1)=1.7182809693185
 
real 0m4.412s
user 0m4.400s
sys 0m0.004s
 
 
alex@thinkpad:~/projects$ time speedcompar/exp.py
exponent( 1.0)=2.71828182846
integral(0..1)=1.71828096932
 
real 0m17.268s
user 0m17.236s
sys 0m0.004s
 
 
alex@thinkpad:~/projects$ time speedcompar/exp.pl
exponent( 1.0)=2.71828182845905
integral(0..1)=1.7182809693185
 
real 0m28.149s
user 0m28.104s
sys 0m0.000s

Indeed lua is really good at floating points numbers operations! It is only 4.5 times slower than the C version! Anonymous was right after all and Perl is busted!

[Image]

Continue to the Part 3

No comments: