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:
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:
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:
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:
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:
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: