Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-11

Faster fannkuch?

7 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

S. Fisher

This is faster than the one at the shootout
(shootout.alioth.debian.org/gp4/benchmark.php?test=fannkuch&lang=fpascal&id=3) on my computer. See if it's faster on yours.

{ The Computer Language Shootout
http://shootout.alioth.debian.org/

contributed by Florian Klaempfl
modified by Micha Nelissen
modified by Vincent Snijders
modified by Steve Fisher

Compile with
fpc -O3 fannkuch.pp
}

{$INLINE ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
type
    TIntegerArray = Array[0..99] of longint;
var
   permu, permu_copy, count: TIntegerArray;
   r, n, answer : longint;
procedure swap(var a, b: longint); inline;
var  tmp: longint;
begin  tmp := a;  a := b;  b := tmp   end;
procedure roll_down( var a : array of longint ); inline;
var  tmp : longint;
begin
  tmp := a[ 0 ];
  move( a[1], a[0], high(a)*sizeof(longint) );
  a[ high(a) ] := tmp;
end;
procedure reverse( var a: array of longint ); inline;
var
  pi, pj : pLongint;
begin
  pi := @a[0];
  pj := @a[high(a)];
  while pi<pj do
  begin
    swap(pi^, pj^);
    inc(pi);
    dec(pj);
  end;
end;
function NextPermutation: boolean;
var
  r0: longint;
begin
  r0 := r; // use local variable
  NextPermutation := true;
  repeat
    if r0 = n then
    begin
      NextPermutation := false;
      break;
    end;
    roll_down( permu[ 0 .. r0 ] );
    dec(count[r0]);
    if count[r0] > 0 then
      break;
    inc(r0);
  until false;
  r := r0;
end;
function fannkuch: longint;
var
  print30, m, i, last, tmp, flips: longint;
begin
  print30 := 0;
  fannkuch := 0;
  m := n - 1;
  // Initial permutation.
  for i := 0 to m do   permu[i] := i;
  r := n;
  repeat
    if print30 < 30 then
    begin
      for i := 0 to m do   write(permu[i] + 1);
      writeln;   inc(print30);
    end;
    while r  1 do
    begin
      count[r-1] := r;
      dec(r);
    end;
    if (permu[0]0) and (permu[m]m) then
    begin
      move(permu[0], permu_copy[0], sizeof(longint)*n);
      flips := 0;
      last := permu_copy[0];
      repeat
        // Reverse part of the array.
        reverse( permu_copy[ 1 .. last-1 ] );
        tmp := permu_copy[ last ];
        permu_copy[ last ] := last;
        last := tmp;
        inc(flips);
      until last = 0;
      if flips > fannkuch then
        fannkuch := flips;
    end;
  until not NextPermutation;
end;
begin
  n := 7;
  if paramCount() = 1 then
    Val(ParamStr(1), n);
  answer := fannkuch;
  writeln('Pfannkuchen(', n, ') = ', answer);
end.

__________________________________________________ Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Florian Klaempfl
to S. Fisher
This is faster than the one at the shootout (shootout.alioth.debian.org/gp4/benchmark.php?test=fannkuch&lang=fpascal&id=3) on my computer. See if it's faster on yours.

Indeed, just submit it.

Show quoted text 133 lines
{ The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Florian Klaempfl modified by Micha Nelissen modified by Vincent Snijders modified by Steve Fisher Compile with fpc -O3 fannkuch.pp } {$INLINE ON} {$OVERFLOWCHECKS OFF} {$RANGECHECKS OFF} type TIntegerArray = Array[0..99] of longint; var permu, permu_copy, count: TIntegerArray; r, n, answer : longint; procedure swap(var a, b: longint); inline; var tmp: longint; begin tmp := a; a := b; b := tmp end; procedure roll_down( var a : array of longint ); inline; var tmp : longint; begin tmp := a[ 0 ]; move( a[1], a[0], high(a)*sizeof(longint) ); a[ high(a) ] := tmp; end; procedure reverse( var a: array of longint ); inline; var pi, pj : pLongint; begin pi := @a[0]; pj := @a[high(a)]; while pi<pj do begin swap(pi^, pj^); inc(pi); dec(pj); end; end; function NextPermutation: boolean; var r0: longint; begin r0 := r; // use local variable NextPermutation := true; repeat if r0 = n then begin NextPermutation := false; break; end; roll_down( permu[ 0 .. r0 ] ); dec(count[r0]); if count[r0] > 0 then break; inc(r0); until false; r := r0; end; function fannkuch: longint; var print30, m, i, last, tmp, flips: longint; begin print30 := 0; fannkuch := 0; m := n - 1; // Initial permutation. for i := 0 to m do permu[i] := i; r := n; repeat if print30 < 30 then begin for i := 0 to m do write(permu[i] + 1); writeln; inc(print30); end; while r 1 do begin count[r-1] := r; dec(r); end; if (permu[0]0) and (permu[m]m) then begin move(permu[0], permu_copy[0], sizeof(longint)*n); flips := 0; last := permu_copy[0]; repeat // Reverse part of the array. reverse( permu_copy[ 1 .. last-1 ] ); tmp := permu_copy[ last ]; permu_copy[ last ] := last; last := tmp; inc(flips); until last = 0; if flips > fannkuch then fannkuch := flips; end; until not NextPermutation; end; begin n := 7; if paramCount() = 1 then Val(ParamStr(1), n); answer := fannkuch; writeln('Pfannkuchen(', n, ') = ', answer); end. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Vincent Snijders
to S. Fisher: This is faster than the one at the shootout (shootout.alioth.debian.org/gp4/benchmark.php?…
S. Fisher wrote
This is faster than the one at the shootout (shootout.alioth.debian.org/gp4/benchmark.php?test=fannkuch&lang=fpascal&id=3) on my computer. See if it's faster on yours.

Quite possible. I made some tweaks so it would work better with the fpc 2.0.4 register allocater, but I knew at that time, that it would have negative effect for the 2.1.x register allocater.

Vincent

S. Fisher
to Florian Klaempfl: Indeed, just submit it.
--- Florian Klaempfl wrote
S. Fisher schrieb: > This is faster than the one at the shootout >

(shootout.alioth.debian.org/gp4/benchmark.php?test=fannkuch&lang=fpascal&id=3)

> on my computer. See if it's faster on yours. Indeed, just submit it.

There's a slight problem. I already submitted it and was told that it was slower. (Actually, the source was a tad different --- low(ary) instead of 0 --- but the executables are identical.)

After the original message was posted, I noticed that the shootout site had accepted it even though it was deemed slower.

It seems strange that this is slower on the shootout's computer when it's faster both on my slow laptop and the 3GHz computer at work.

Under windoze, I've found that programs take longer to run the first time they are executed after recompilation. Is Linux the same way?

So the shootout site shows this as slightly slower than the previous Pascal program. Maybe this will change when the programs are tested again or when the site's owners get a new computer.

__________________________________________________ Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

L
to S. Fisher
Under windoze, I've found that programs take longer to run the first time they are executed after recompilation. Is Linux the same way?

This may have something to do with certain code/data being cached.. I'm not sure what since a console program doesn't use many DLL's.. It must cache the exe code segment or data segment.

For example a program that uses many DLL's will load faster if it is opened the second time. As for programs that don't use DLL's, I guess the program is somehow cached for later use. This is one reason CGI programs are very fast.. because the same CGI program is being called over and over and over again.

L505

S. Fisher
to Florian Klaempfl
--- Florian Klaempfl wrote 7 lines
S. Fisher schrieb: > It seems strange that this is slower on the shootout's computer > when it's faster both on my slow laptop and the 3GHz computer > at work. The shootout uses a P4 which behaves sometimes strange regarding optimization.

Well, I made another version that's faster yet, and now the site is showing it as the fastest Pascal program.

It's about 1.5 times as slow as C.

In order for it to be even faster, I think the compiler needs to optimize this more:

  while pi<pj do
  begin
    swap(pi^, pj^);
    inc(pi);
    dec(pj);
  end;

__________________________________________________ Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com