Before doing any more work on this benchmarking project, I was wondering if any one else thinks the effort is worth it.

Although it is early days, it seemed reasonable to start setting up a framework for benchmarking perl6 algorithms against implementations/releases and against other languages.

The Alioth shootout is one benchmarking system, with thirteen benchmark programs. I have converted one benchmark to perl6 (two programs, slightly different). Gradually working on the remainder.

The results below compare perl, perl6, ruby, php, and python programs. (I haven't got java or gcc to work yet). The input data are very small, since perl6 is still weak.

Hopefully the table formatting below will come out properly.

name    lang    id      n       size(B)         cpu(s)  mem(KB)         status  
load    elapsed(s)
nbody   python  1       30      1329    0.01    0       0       %       0
nbody   php     2       30      1333    0.01    0       0       %       0
nbody   perl    1       30      1556    0.01    0       0       %       0
nbody   ruby    2       30      1326    0       0       0       %       0
nbody   php     3       30      1240    0.01    0       0       100% 100%       
0.02
nbody   python  4       30      1238    0.02    0       0       0% 100%         
0.02
nbody   php     1       30      1383    0.01    0       0       50% 100%        
0.02
nbody   perl6   2       30      1320    5.41    206776  0       100% 13%        
5.42
nbody   perl6   1       30      1394    5.64    208820  0       32% 89%         
5.68


see http://shootout.alioth.debian.org/ for more info on the algorithms.

There are many factors that can be considered when benchmarking, including IO and OS.

It seemed to me it would be a good idea to fix on some "elegant" form of the perl6 implementation. By keeping the program the same, it will be possible to track how developments implementations affect speed/memory size.

The perl6 program is given below. It still retains the form of the original perl, the python version is quite different.

Richard
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# contributed by Christoph Bauer
# converted into Perl by Márton Papp
# converted to perl6 by Richard Hainsworth

my $solar-mass = (4 * pi * pi);
my $days-per-year = 365.24;

#  Globals for arrays... Oh well.
# Globals introduced to speed up perl.
# @ns = ( sun, jupiter, saturn, uranus, neptune )
my @xs = (0, 4.84143144246472090e+00, 8.34336671824457987e+00, 1.28943695621391310e+01, 1.53796971148509165e+01); my @ys = (0, -1.16032004402742839e+00, 4.12479856412430479e+00, -1.51111514016986312e+01, -2.59193146099879641e+01); my @zs = (0, -1.03622044471123109e-01, -4.03523417114321381e-01, -2.23307578892655734e-01, 1.79258772950371181e-01);
my @vxs = $days-per-year <<*<<
(0, 1.66007664274403694e-03, -2.76742510726862411e-03, 2.96460137564761618e-03, 2.68067772490389322e-03);
my @vys = $days-per-year <<*<<
(0, 7.69901118419740425e-03, 4.99852801234917238e-03, 2.37847173959480950e-03, 1.62824170038242295e-03);
my @vzs = $days-per-year <<*<<
(0, -6.90460016972063023e-05, 2.30417297573763929e-05, -2.96589568540237556e-05, -9.51592254519715870e-05);
my @mass = $solar-mass <<*<<
(1, 9.54791938424326609e-04, 2.85885980666130812e-04, 4.36624404335156298e-05, 5.15138902046611451e-05);

# Almost every iteration is a range, so keep the last index rather than a count.
my $last = +@xs;

@vxs[0] = - ( [+] @vxs Z* @mass ) / $solar-mass;
@vys[0] = - ( [+] @vys Z* @mass ) / $solar-mass;
@vzs[0] = - ( [+] @vzs Z* @mass ) / $solar-mass;

sub advance($dt)
{
  my ($mm, $mm2, $j, $dx, $dy, $dz, $distance, $mag);

  for ^$last {
    for $_ ^..^ $last -> $j {
      $dx = @xs[$_] - @xs[$j];
      $dy = @ys[$_] - @ys[$j];
      $dz = @zs[$_] - @zs[$j];
      $distance = sqrt($dx * $dx + $dy * $dy + $dz * $dz);
      $mag = $dt / ($distance * $distance * $distance);
      $mm = @mass[$_] * $mag;
      $mm2 = @mass[$j] * $mag;
      @vxs[$_] -= $dx * $mm2;
      @vxs[$j] += $dx * $mm;
      @vys[$_] -= $dy * $mm2;
      @vys[$j] += $dy * $mm;
      @vzs[$_] -= $dz * $mm2;
      @vzs[$j] += $dz * $mm;
    }
# We're done with planet $_ at this point
# This could be done in a seperate loop, but it's slower
    @xs[$_] += $dt * @vxs[$_];
    @ys[$_] += $dt * @vys[$_];
    @zs[$_] += $dt * @vzs[$_];
  }
}

sub energy
{
  my ($dx, $dy, $dz, $distance);

  my $e = 0.0;
  for ^$last -> $i {
    $e += 0.5 * @mass[$i] *
(@vxs[$i] * @vxs[$i] + @vys[$i] * @vys[$i] + @vzs[$i] * @vzs[$i]);
    for $i ^..^ $last {
      $dx = @xs[$i] - @xs[$_];
      $dy = @ys[$i] - @ys[$_];
      $dz = @zs[$i] - @zs[$_];
      $distance = sqrt($dx * $dx + $dy * $dy + $dz * $dz);
      $e -= (@mass[$i] * @mass[$_]) / $distance;
    }
  }
  return $e;
}


multi MAIN( $n ) {
  energy.fmt("%.9f").say;
  advance(0.01) for ^$n;
  energy.fmt("%.9f").say;
}

multi MAIN('test') {
  use Test;
  plan *;

  is energy.fmt("%.9f"), -0.169075164, 'energy 0';
  advance(0.01) for ^123;
  is energy.fmt("%.9f"), -0.169044806, 'energy 123';

  done();
}


Reply via email to