Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #24314
| From | "WJ" <w_a_x_man@yahoo.com> |
|---|---|
| Newsgroups | comp.lang.forth |
| Subject | Fortran proves Forth a stone-age toy |
| Date | 2013-07-09 07:14 +0000 |
| Organization | A noiseless patient Spider |
| Message-ID | <krgd8b$vji$1@dont-email.me> (permalink) |
I threw together a Fortran version of the Fannkuch program that
runs in only 0.203 seconds on my tired, old, battered laptop.
That leaves the iForth version in the dust.
In addition, the Fortran program is immeasurably more readable
and maintainable.
! 0.203125000 seconds on Intel Core2 Duo CPU P8600 @ 2.4GHz
! GFortran (gcc version 4.8.0 20130302)
! Compile with
! gfortran -O3 -march=native fannkuch.f95
program fannkuch
implicit none
integer, parameter :: N = 10
integer :: perm(N), permp(N), counts(N), tmp, i, flips
integer :: maxflips = 0, prn_count = 0, r = N
real :: t1, t2
call cpu_time( t1 )
do i = 1, N
permp(i) = i
counts(i) = 0
end do
do while (.true.)
if (prn_count < 30) then
prn_count = prn_count + 1
call print_vector( permp )
end if
do i = 2, r
counts(i) = i
end do
r = 1
if ( permp(1) /= 1 .and. permp(N) /= N ) then
perm = permp
flips = flipping( perm )
if (flips > maxflips) maxflips = flips
end if
do while (.true.)
if (N == r) then
print "(A:,I0,A:,I0)", "Pfannkuchen(", N, ") = ", maxflips
call cpu_time( t2 )
print *, t2 - t1
stop
end if
i = r + 1
! --- Shift left.
tmp = permp(1)
permp(1:i-1) = permp(2:i)
permp(i) = tmp
counts(i) = counts(i) - 1
if (counts(i) > 0) exit
r = r + 1
end do
end do
contains
integer function flipping( perm )
implicit none
integer :: perm(N)
integer :: k, tmp, flips
flips = 0
k = perm(1)
do while (k > 1)
! --- Reverse part.
if (k > 3) call reverse_some( perm, k - 1 )
flips = flips + 1
tmp = perm(k)
perm(k) = k
k = tmp
end do
flipping = flips
end function flipping
subroutine print_vector( v )
implicit none
integer :: v(N), i
do i = 1, ubound(v,1)
write (*, "(I0)", advance="no"), v(i)
end do
print *, ""
end subroutine
subroutine reverse_some( vector, top )
implicit none
integer :: vector(N), top, i, j, tmp
i = 2
j = top
do while (i < j)
tmp = vector( i )
vector( i ) = vector( j )
vector( j ) = tmp
j = j - 1
i = i + 1
end do
end
end program fannkuch
> From: mhx@iae.nl (Marcel Hendrix)
> Subject: Pfannkuch revisited
> Date: Wed, 26 Dec 2012 10:06:52 +0200
> Message-ID: <83979309918435@frunobulax.edu>
> Lines: 180
>
> Pfannkuch (Computer Language Shootout) was mentioned recently ...
>
> Back in 2006 I wasn't happy that 580 ms was the best
> iForth could do, compared to 330 ms in 'C'.
>
> Tonight I looked at it again. Based on Stephen Pelc's remarks I removed
> all local variables -- that shaved off about 100 ms. Doing the I/O
> differently speeded it up another 100 ms. The Forth and C version now
> behave nearly the same. The C version is using ints where Forth uses bytes.
> Timings are done on the same machine, I recompiled and optimized the C
> version as good as it would go. (It is a 64bit program, but ints are 32 bits
> on Windows).
>
> -marcel
>
> -- -------------------------------------------
> (*
> * LANGUAGE : ANS Forth with extensions
> * PROJECT : Forth Environments
> * DESCRIPTION : Fannkuch benchmark
> * CATEGORY : Benchmarks
> * AUTHOR : Marcel Hendrix
> * LAST CHANGE : June 10, 2006, Marcel Hendrix
> * LAST CHANGE : Wednesday, December 26, 2012, 00:12, Marcel Hendrix
> *)
>
>
> NEEDS -miscutil
>
> REVISION -fannkuch5 "--- Fannkuch (C) Version 5.00 ---"
>
>
> DOC
> (*
> fannkuch benchmark | C gcc | fannkuch full data
>
> fannkuch C gcc program
> N Full CPU Time s Memory Use KB GZip Bytes
> 10 0.45 16,384 612
>
> /*
> * The Computer Language Shootout
> * http://shootout.alioth.debian.org/
> * Contributed by Heiner Marxen
> *
> * "fannkuch" for C gcc
> *
> * $Id: fannkuch-gcc.code,v 1.33 2006/02/25 16:38:58 igouy-guest Exp $
> */
>
> PROGRAM OUTPUT
> ==============
> 12345678910
> 21345678910
> 23145678910
> 32145678910
> 31245678910
> 13245678910
> 23415678910
> 32415678910
> 34215678910
> 43215678910
> 42315678910
> 24315678910
> 34125678910
> 43125678910
> 41325678910
> 14325678910
> 13425678910
> 31425678910
> 41235678910
> 14235678910
> 12435678910
> 21435678910
> 24135678910
> 42135678910
> 23451678910
> 32451678910
> 34251678910
> 43251678910
> 42351678910
> 24351678910
> Pfannkuchen(10) = 38
> *)
> ENDDOC
>
> #10 =: N
> N 1- =: N1
>
> CREATE perm N ALLOT
> CREATE perm1 N ALLOT
> CREATE counts N ALLOT
>
> 0 VALUE didpr
> 0 VALUE flips
> 0 VALUE flipsMax
>
> CREATE obuffer #4096 CHARS ALLOT
>
> : oinit ( -- ) obuffer 0! ;
> : >out ( c-addr u -- ) obuffer CELLPLACE+ ;
> : CR>out ( -- ) $CR COUNT >out ;
> : .pan ( -- ) CR>out N 0 DO perm1 I + C@ 1+ (0DEC.R) >out LOOP ;
>
> : XCH ( ix1 ix2 -- )
> perm + SWAP perm +
> DUP C@ >R SWAP DUP C@ ( -- addr1 addr2 n2 )
> ROT C! R> SWAP C! ;
>
> -- N = 10
> 64BIT?
> [IF]
> : special-move ( -- )
> perm1 1+ @ perm 1+ !
> perm1 9 + C@ perm 9 + C! ;
> [ELSE]
> : special-move ( -- )
> perm1 1+ @ perm 1+ !
> perm1 5 + @ perm 5 + !
> perm1 9 + C@ perm 9 + C! ;
> [THEN]
>
> : fannkuch ( -- u )
> N 1 < IF 0 EXIT ENDIF
> CLEAR didpr CLEAR flips CLEAR flipsMaX
> N >R
> perm1 N 0 DO I SWAP C!+ LOOP DROP \ initial (trivial) permute
> BEGIN
> didpr #30 < IF .pan 1 +TO didpr ENDIF
>
> counts R@ 1- + R>
> BEGIN DUP 1 <>
> WHILE DUP 2 PICK C!
> 1- SWAP 1- SWAP
> REPEAT >R DROP
>
> perm1 C@ 0=
> perm1 N1 + C@ N1 = OR 0=
> IF 0 TO flips
> special-move
> perm1 C@ >R \ cache perm[0] on R
> BEGIN \ k1 != 0 ==> k1>0
> 1 R@ 1- ( -- i1 j1 )
> BEGIN 2DUP <
> WHILE 2DUP XCH
> 1- SWAP 1+ SWAP
> REPEAT 2DROP
> R> DUP perm + DUP C@ >R C! ( R: -- j1 )
> 1 +TO flips
> R@ 0=
> UNTIL -R
> flipsMax flips < IF flips TO flipsMax ENDIF
> ENDIF
> BEGIN R@ N = IF flipsMax -R EXIT ENDIF \ rotate down perm[0..r] by one
> perm1 C@ ( perm0) 0
> BEGIN DUP R@ <
> WHILE 1+
> DUP perm1 + DUP C@ SWAP 1- C!
> REPEAT DROP ( perm0)
> perm1 R@ + C!
> counts R@ + DUP C@ 1- DUP ROT C! 0<=
> WHILE R> 1+ >R
> REPEAT
> AGAIN ;
>
> : main ( -- )
> oinit
> TIMER-RESET
> fannkuch
> CR>out S" Pfannkuchen(" >out N (0DEC.R) >out S" ) = " >out (.) >out
> CR .ELAPSED
> obuffer @+ TYPE ;
>
> :ABOUT CR ." Try: main -- Standard Shootout test (VC++ 6.0: 333 ms). Should be around 352 ms."
> CR ." Using TYPE gives 450 ms." ;
>
> .ABOUT -fannkuch5 CR
>
> (* End of Source *)
>
Back to comp.lang.forth | Previous | Next — Next in thread | Find similar
Fortran proves Forth a stone-age toy "WJ" <w_a_x_man@yahoo.com> - 2013-07-09 07:14 +0000
Re: Fortran proves Forth a stone-age toy m.a.m.hendrix@tue.nl - 2013-07-09 01:03 -0700
Re: Fortran proves Forth a stone-age toy "Ed" <invalid@invalid.com> - 2013-07-09 19:32 +1000
Re: Fortran proves Forth a stone-age toy "WJ" <w_a_x_man@yahoo.com> - 2013-07-09 22:26 +0000
Re: Fortran proves Forth a stone-age toy "WJ" <w_a_x_man@yahoo.com> - 2013-07-11 00:01 +0000
Re: Fortran proves Forth a stone-age toy "WJ" <w_a_x_man@yahoo.com> - 2013-07-12 12:10 +0000
Re: Fortran proves Forth a stone-age toy hughaguilar96@yahoo.com - 2013-07-10 11:10 -0700
Re: Fortran proves Forth a stone-age toy "Rod Pemberton" <do_not_have@notemailnotq.cpm> - 2013-07-12 03:14 -0400
Re: Fortran proves Forth a stone-age toy Richard Owlett <rowlett@pcnetinc.com> - 2013-07-12 05:14 -0500
csiph-web