[offtopic] FreePascal

General discussion for topics related to the FreeBASIC project or its community.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

marcov wrote:as alternative going to rock bottom pointer to char handling.
Since I have an expert at hand here: What would I have to change to get the 'rock bottom' version?

Code: Select all

program RecallFPC;	// simple example
uses
 Classes, SysUtils, DateUtils, Crt;	// FB example (includes MB example; 10ms loading, 2.6 searching)
var
  Str: TStringList;
  ct, mypos, matches: LongInt;
  D1, D2: TDateTime;
begin
  Str := TStringList.Create;
  write(ParamStr(1)+': loading ');
  D1:=Now;
  Str.LoadFromFile(ParamStr(1));
  D2:=Now;
  Writeln(IntToStr(Str.Count)+' strings took ', MilliSecondsBetween(D1, D2), ' milliseconds');
  Write('finding ');
  D1:=Now;
	repeat
		//writeln(Str[ct]);
		mypos:=Pos('Devil', Str[ct]);
		if (mypos>0) then matches:=matches+1;
		ct:=ct+1;
	until ct>=Str.Count-1;
	D2:=Now;
	Writeln(IntToStr(matches)+' matches took ', MilliSecondsBetween(D1, D2), ' milliseconds');
	Str.Free;
	ReadKey;
end.
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

jj2007 wrote:
marcov wrote:as alternative going to rock bottom pointer to char handling.
Since I have an expert at hand here: What would I have to change to get the 'rock bottom' version?
Rock bottom, means doing all strings ops (besides a few like strlen) yourself. No string type overhead, but little RTL support.

That said, I would simply use classic pascal read(f,s) with a settextbuf set, and directly do the pos() without first storing all strings.

Code: Select all

{$mode delphi} // use unlimited strings.
uses sysutils;
var f : textfile;
     buf: array[0..8191] of byte; // default buffer is 128 byte, which is smallish.
      matches:integer; 
      s:string;
begin
  assignfile(f,paramstr(1));
  reset(f);
  settextbuf(f,buf);
  matches:=0;
  while not eof(f) do
    begin
      readln(f,s);
     if (Pos('Devil', S)>0) then 
        matches:=matches+1;
      end;
    closefile(f); 
 end.
Needs checks and matches output, but that is not performance sensitive.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

Works fine but is about 4-5 times slower than my version... it seems LoadFile is more efficient than readln.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

Marcov
Is there a .zip download for fp?
I don't want to run the .exe installer in win 10.
The old dos ide is too awkward.(I have it from an older version)
Lazarus is too much.
I have the dev-pas ide, I only need to extract the fp binaries somewhere and use dev-pas.
I see a gcc.exe in the older version, but I believe gcc doesn't entirely run fp.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

You can use a simple batch file to compile FPC:

Code: Select all

echo.
echo *** compiling %1 ***
echo.
set MyExe=%~n1.exe
FPC\3.0.4\bin\i386-win32\fpc.exe -v0 "%1"
echo.
IF %ERRORLEVEL%==0 (
  echo *** running %~n1.exe ***
  start %MyExe% "%2"
) else (
  echo *** compilation error - sorry! ***
)
%1 is the source, %2 is an argument passed to your exe. The "start" means it opens a new console window; make sure you have a ReadKey; at the end.

In case somebody needs a 20MB textfile for testing, here is one.
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

dodicat wrote:Marcov
Is there a .zip download for fp?
I don't want to run the .exe installer in win 10.
No.
I see a gcc.exe in the older version, but I believe gcc doesn't entirely run fp.
FPC doesn't, but windres, the windows resource compiler needs something. In versions >=2.4.0, some kinds of resources are generated by FPC/Lazarus itself, so it is used less. Some work is being done to eliminate it entirely.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

compiling this https://benchmarksgame-team.pages.debia ... cal-1.html with fpc -O3 nbody.pas and executing nbody.exe 50000000 FreePascal's time is about the same as that of FreeBasic with -O2
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

srvaldez wrote:FreePascal's time is about the same as that of FreeBasic with -O2
Not a surprise, the benchmark is heavily skewed towards math functions, sqrt in particular. The limiting factor is the hardware, i.e. the FPU.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

srvaldez
for pascal sqr
did you use
Somenumber*somenumber
or
somenumber^2
?
Here is my translation

Code: Select all

 

Type body
    ' Body = record
    As String body
    Dim As Double  x, y, z, _
    vx, vy, vz,mass
End Type



Const pi = 3.141592653589793 
Const    solarMass = 4 * (pi)^2 
Const   daysPerYear = 365.24

'type

Dim shared As body tbody(1 To 5)
For n As Long=1 To 5
    Select Case n
    Case 1
        With tbody(1)
            .body= "Sun "
            .x=0: .y=0: .z=0:  .vx=0: .vy=0: .vz=0: .mass= solarMass 
        End With
    Case 2
        With tbody(2)
            .body="Jupiter"
            .x=    4.84143144246472090e+00
            .y=   -1.16032004402742839e+00
            .z=   -1.03622044471123109e-01
            .vx=   1.66007664274403694e-03 * daysPerYear
            .vy=   7.69901118419740425e-03 * daysPerYear
            .vz=  -6.90460016972063023e-05 * daysPerYear
            .mass= 9.54791938424326609e-04 * solarMass 
        End With
    Case 3
        With tbody(3)
            .body="Saturn "
            .x=    8.34336671824457987e+00
            .y=    4.12479856412430479e+00
            .z=   -4.03523417114321381e-01
            .vx=  -2.76742510726862411e-03 * daysPerYear
            .vy=   4.99852801234917238e-03 * daysPerYear
            .vz=   2.30417297573763929e-05 * daysPerYear
            .mass= 2.85885980666130812e-04 * solarMass 
        End With
    Case 4
        With tbody(4)
            .body="Uranus "
            .x=    1.28943695621391310e+01
            .y=   -1.51111514016986312e+01
            .z=   -2.23307578892655734e-01
            .vx=   2.96460137564761618e-03 * daysPerYear
            .vy=   2.37847173959480950e-03 * daysPerYear
            .vz=  -2.96589568540237556e-05 * daysPerYear
            .mass= 4.36624404335156298e-05 * solarMass 
        End With
    Case 5
        With tbody(5)
            .body= "Neptune "
            .x=    1.53796971148509165e+01
            .y=   -2.59193146099879641e+01
            .z=    1.79258772950371181e-01
            .vx=   2.68067772490389322e-03 * daysPerYear
            .vy=   1.62824170038242295e-03 * daysPerYear
            .vz=  -9.51592254519715870e-05 * daysPerYear
            .mass= 5.15138902046611451e-05 * solarMass
        End With
    End Select
Next n
sub offsetMomentum()
    dim as double px,py,pz
    dim as integer i

 ' px:=0.0: py:=0.0; pz:=0.0;
  for i = lbound(tbody)+1 to ubound(tbody)
    'with b(i)
    'begin
      px = px - tbody(i).vx *  tbody(i).mass
      py = py - tbody(i).vy *  tbody(i).mass
      pz = pz - tbody(i).vz *  tbody(i).mass
      'end with
    next
  tbody(lbound(tbody)).vx = px / solarMass
  tbody(lbound(tbody)).vy = py / solarMass
  tbody(lbound(tbody)).vz = pz / solarMass
end sub

function distance(i as integer,j as integer) as double
  distance = sqr((tbody(i).x-tbody(j).x)^2 + (tbody(i).y-tbody(j).y)^2 +(tbody(i).z-tbody(j).z)^2)
end function

function energy as double
 dim as integer i,j 
  dim as double result = 0.0
  for i = lbound(tbody) to ubound(tbody)
      result = result + tbody(i).mass * ( tbody(i).vx^2 + tbody(i).vy^2 + tbody(i).vz^2 ) / 2
      for j = i+1 to ubound(tbody)
        result = result - tbody(i).mass * tbody(j).mass / distance(i,j)
    next
    next
return result
end function

sub advance(dt as double)
'var i,j : integer;
dim as integer i,j
  dim as double  dx,dy,dz,mag 
  dim as body ptr  bi,bj 

  bi=@tbody(lbound(tbody))'b[low(b)];
  for i = lbound(tbody) to ubound(tbody)-1 'do begin
    bj = bi
    for j = i+1 to ubound(tbody) 'do
   ' begin
      'inc(bj);
      bj+=1
      dx = bi->x - bj->x
      dy = bi->y - bj->y
      dz = bi->z - bj->z
      mag = dt / (sqr((dx)^2+(dy)^2+(dz)^2)*((dx)^2+(dy)^2+(dz)^2))
      bi->vx = bi->vx - dx * bj->mass * mag
      bi->vy = bi->vy - dy * bj->mass * mag
      bi->vz = bi->vz - dz * bj->mass * mag
      bj->vx = bj->vx + dx * bi->mass * mag
      bj->vy = bj->vy + dy * bi->mass * mag
      bj->vz = bj->vz + dz * bi->mass * mag
    next
    bi+=1
    'inc(bi);
   next
  
  bi=@tbody(lbound(tbody))
  for i = lbound(tbody) to ubound(tbody)
    'with bi^ do
    'begin
      bi-> x = bi->x + dt * bi->vx
      bi->y = bi->y + dt * bi->vy
      bi->z = bi->z + dt * bi->vz
      bi+=1
   ' end;
   ' inc(bi);
  next
end sub


    dim as integer i,j
dim as double t=timer
  'SetPrecisionMode(pmDouble);
  offsetMomentum
  print using "##.#########"; energy
  'writeln(energy:0:9);
  'Val(ParamStr(1), n, i);
  for i = 1 to 50000000' do advance(0.01);
      advance(.01)
      'print energy
  next
 print using "##.#########";energy
 print timer-t
 ' writeln(energy:0:9);
 sleep




'end;

  
and my -gen gas results

Code: Select all

-0.169075164
-0.169059907
 23.63915837392179
 
with 64 bit -O3 I get about 10 seconds.
But is it fair to present freebasic -gen gcc, because this is actually a C speed.
I'll try somenumber*somenumber for pascal sqr later.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

@dodicat
I have been very lazy lately, so I used the one I had translated from C some time ago https://benchmarksgame-team.pages.debia ... gcc-1.html
I think you should use Somenumber*somenumber for sqr

@jj2007
have tried your FreePascal test with -O3 ?
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

running the actual pascal code in freepascal via

Code: Select all

dim as double t=timer
shell "test1 50000000"
print timer-t
sleep  
I get

Code: Select all

-0.169075164
-0.169059907
 34.78720054423098
 
so I have -gen gas beating freepascal (using somenumber^2 )
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

srvaldez wrote:@jj2007
have tried your FreePascal test with -O3 ?
Yes. 11 seconds instead of 17 for 50 Mio iterations.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

@dodicat
the FreePascal time seems a bit high, I borrowed a bit code from jj2007 to make the program time itself

Code: Select all

{ The Computer Language Benchmarks Game
  https://salsa.debian.org/benchmarksgame-team/benchmarksgame/

  contributed by Ian Osgood,
  modified by Florian Klaempfl
  modified by Ales Katona
  modified by Vincent Snijders
}

{$mode objfpc}

program n_body;

uses Math, SysUtils, DateUtils;

type
  Body = record
    x, y, z,
    vx, vy, vz,
    mass : double;
  end;
  PBody = ^Body;

const pi = 3.141592653589793;
      solarMass = 4 * sqr(pi);
      daysPerYear = 365.24;

type
  tbody = array[1..5] of Body;

const b : tbody = (
  { Sun }
  ( x:0; y:0; z:0;  vx:0; vy:0; vz:0;  mass: solarMass ),
  { Jupiter }
  ( x:    4.84143144246472090e+00;
    y:   -1.16032004402742839e+00;
    z:   -1.03622044471123109e-01;
    vx:   1.66007664274403694e-03 * daysPerYear;
    vy:   7.69901118419740425e-03 * daysPerYear;
    vz:  -6.90460016972063023e-05 * daysPerYear;
    mass: 9.54791938424326609e-04 * solarMass ),
  { Saturn }
  ( x:    8.34336671824457987e+00;
    y:    4.12479856412430479e+00;
    z:   -4.03523417114321381e-01;
    vx:  -2.76742510726862411e-03 * daysPerYear;
    vy:   4.99852801234917238e-03 * daysPerYear;
    vz:   2.30417297573763929e-05 * daysPerYear;
    mass: 2.85885980666130812e-04 * solarMass ),
  { Uranus }
  ( x:    1.28943695621391310e+01;
    y:   -1.51111514016986312e+01;
    z:   -2.23307578892655734e-01;
    vx:   2.96460137564761618e-03 * daysPerYear;
    vy:   2.37847173959480950e-03 * daysPerYear;
    vz:  -2.96589568540237556e-05 * daysPerYear;
    mass: 4.36624404335156298e-05 * solarMass ),
  { Neptune }
  ( x:    1.53796971148509165e+01;
    y:   -2.59193146099879641e+01;
    z:    1.79258772950371181e-01;
    vx:   2.68067772490389322e-03 * daysPerYear;
    vy:   1.62824170038242295e-03 * daysPerYear;
    vz:  -9.51592254519715870e-05 * daysPerYear;
    mass: 5.15138902046611451e-05 * solarMass )
);

procedure offsetMomentum;
var px,py,pz : double;
    i : integer;
begin
  px:=0.0; py:=0.0; pz:=0.0;
  for i := low(b)+1 to high(b) do
    with b[i] do
    begin
      px := px - vx * mass;
      py := py - vy * mass;
      pz := pz - vz * mass;
    end;
  b[low(b)].vx := px / solarMass;
  b[low(b)].vy := py / solarMass;
  b[low(b)].vz := pz / solarMass;
end;

function distance(i,j : integer) : double;
begin
  distance := sqrt(sqr(b[i].x-b[j].x) + sqr(b[i].y-b[j].y) +
sqr(b[i].z-b[j].z));
end;

function energy : double;
var
  i,j : integer;
begin
  result := 0.0;
  for i := low(b) to high(b) do
    with b[i] do
    begin
      result := result + mass * (sqr(vx) + sqr(vy) + sqr(vz)) / 2;
      for j := i+1 to high(b) do
        result := result - mass * b[j].mass / distance(i,j);
    end;
end;

procedure advance(dt : double);
var i,j : integer;
    dx,dy,dz,mag : double;
    bi,bj : PBody;
begin
  bi:=@b[low(b)];
  for i := low(b) to high(b)-1 do begin
    bj := bi;
    for j := i+1 to high(b) do
    begin
      inc(bj);
      dx := bi^.x - bj^.x;
      dy := bi^.y - bj^.y;
      dz := bi^.z - bj^.z;
      mag := dt / (sqrt(sqr(dx)+sqr(dy)+sqr(dz))*(sqr(dx)+sqr(dy)+sqr(dz)));
      bi^.vx := bi^.vx - dx * bj^.mass * mag;
      bi^.vy := bi^.vy - dy * bj^.mass * mag;
      bi^.vz := bi^.vz - dz * bj^.mass * mag;
      bj^.vx := bj^.vx + dx * bi^.mass * mag;
      bj^.vy := bj^.vy + dy * bi^.mass * mag;
      bj^.vz := bj^.vz + dz * bi^.mass * mag;
    end;
    inc(bi);
  end;
  bi:=@b[low(b)];
  for i := low(b) to high(b) do begin
    with bi^ do
    begin
      x := x + dt * vx;
      y := y + dt * vy;
      z := z + dt * vz;
    end;
    inc(bi);
  end;
end;

var i : integer;
    n : Integer;
	D1, D2: TDateTime;
begin
  D1:=Now;
  SetPrecisionMode(pmDouble);
  offsetMomentum;
  writeln(energy:0:9);
  //Val(ParamStr(1), n, i);
  n := 50000000;
  for i := 1 to n do advance(0.01);
  writeln(energy:0:9);
  D2:=Now;
  Writeln( MilliSecondsBetween(D1, D2), ' milliseconds');
end.
suggest you compile with -O3 or -O4
my times were about 11 seconds on both the FP and FB
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

I get about 10 seconds with -gen gcc -Wc -O3
I get about the same with srvaldez's c code compiling directly with gcc (obviously, it's the same thing)
I get about 34 seconds with my freepascal compiler (selecting BEST speed in the ide which is O3 in the compile log)

But my freepascal is old(I copied it from an old machine)
C:\Dev-Pas\Bin>fpc -version
Free Pascal Compiler version 1.0.6 [2002/04/23] for i386
Copyright (c) 1993-2002 by Florian Klaempfl
Marcov says there is no zip file for the latest fp, so that has stopped me.
I cannot run the risk of using a .exe installer on win 10. (Does it write to the registry?, does it put files all over windows?)
I know it is free, but any half decent compiler should have the option of a .zip.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

I understand your concern, perhaps Marcov can answer your questions.
Post Reply