Forth Benchmarks


Vintage Computer Festival Europa 2011

30 April 2011

Forth Benchmarks

Warum?

Forth Versionen

Forth Crashcourse

Forth Kernel

Benchmarks

Warum Forth Benchmarks





Hackerfunk.ch im Dezember 2010

Warum Forth Benchmarks





Eine Diskussion über Z80 und 6502

Warum Forth Benchmarks





die MHz Angabe einer CPU sagt wenig über die Leistungsfähigkeit aus

Warum Forth Benchmarks





Assembler Benchmarks sind schwer portierbar zwischen CPU Architekturen

Warum Forth Benchmarks





Forth ist auf den meisten CPU Architekturen vorhanden

Warum Forth Benchmarks





Forth ist besser standardisiert als z.B. BASIC

Forth Versionen





Forth 77

Forth Versionen





FIG-Forth (FIG = Forth Interest Group)

Forth Versionen





Forth 79

Forth Versionen





Forth 83

Forth Versionen





ANSI Forth (1994)

Forth Versionen





Forth 200x

Forth Versionen

Forth ist immer erweiterbar

eine fehlende Funktion kann nachgerüstet werden

aus einem Forth 77 System kann ein Forth 83 (oder ein Forth 200x) System entstehen

ein Forth System veraltet nicht!

Forth Crashcourse 1

Eine kurze Einfuehrung in Forth

die Befehle (Wörter) der Benchmarkprogramme werden erklaert

Syntax


Ein Wort ist eine Sequenz von beliebigen Zeichen (außer Leerzeichen).

Ein "WORT" ist die Funktionseinheit eines Forth Systems (vergleichbar mit Prozeduren oder Funktionen)

Wörter werden durch Leerzeichen voneinander getrennt.

gültige Forth Wörter:

Sicherheit


Wichtig: in Forth gibt es nur die Sicherheitsnetze, welche der Programmierer selbst anbringt

d.h. normalerweise KEINE!

Forth steht dem Programmierer nicht im Weg

Was ist Forth


Ein ultimativ erweiterbares Programmiersystem

wenig Regeln, keine Syntax

der Programmierer hat volle Kontrolle über Forth .... und das System

Stack


Das auffälligste Merkmal von Forth ist der Stack (Stapelspeicher). Wenn man eine Zahl eintippt, wird diese auf den Stack geschoben.

Der Stack ist ein LIFO (Last In, First Out) Speicher.

Mit ".s" kann man sich den Inhalt des Stacks anschauen.

		1 2 3 .s
	

“.” (Dot)


Mit “.” kann man die Zahl des jeweils obersten Stackelements (TOS, Top of Stack) ausdrucken

		1 2 3 . . . [RTN]
	

Arithmetik


Die arithmetischen Operatoren +, -, *, / und mod arbeiten immer auf den obersten beiden Stack-Elementen (Postfix-Schreibweise):

		2 2 + . [RTN]
		2 1 - . [RTN]
		7 3 mod . [RTN]
	

Arithmetik 2


Klammern sind überflüssig, die Reihenfolge der Ausführung und die Operanden ergeben sich eindeutig durch die Anordnung der Wörter:

		3 4 + 5 * .
		3 4 5 * + .
	

Stackkommentare


Bei der Dokumentation von Forth Wörtern werden die Änderungen des Stacks in Klammern angedeutet

Beispiele:

		. ( n -- ) 
		+ ( n n - n )
	

SWAP


vertauscht die beiden obersten Elemente des Stacks

		SWAP ( x y -- y x )
	

DUP


erstellt vom obersten Stack-Element eine Kopie

		DUP ( x -- x x )
	

DROP


entfernt das oberste Stack-Element (spurlos)

		DROP ( x -- )
	

OVER


legt eine Kopie des 2ten Stackeintrages auf den Stack

		OVER ( x1 x2 - x1 x2 x1 )
	

NIP


entfernt das zweit-oberste Stack-Element (wieder spurlos)

		NIP ( x y -- y )
	

TUCK


schiebt eine Kopie des obersten Stack-Elements unter das zweite Element

		TUCK ( x1 x2 -- x2 x1 x2 )
	

ROT


rotiert die obersten 3 Stackelemente

		ROT ( x1 x2 x3 -- x2 x3 x1 )
	

-ROT


rotiert die obersten 3 Stackelemente (andersherum)

		-ROT ( x1 x2 x3 -- x3 x1 x2 )
	

Kommentare


		\ das ist ein Kommentar bis zum Zeilenende 
		( das ist ein Kommentar bis zur schliessenden Klammer ) .s
		.( Dieser Kommentar wird bei der Ausführung ausgegeben )

\, ( und .( sind normale Forth-Wörter und muessen daher durch Leerzeichen vom nachfolgenden Text getrennt werden.

Wörter definieren


Definitionen sind das Äquivalent zu Prozeduren in anderen Programmiersprachen:

		: quadrat ( n -- n^2 ) dup * ; 
		
		5 quadrat . 
		
		7 quadrat .
	

Wörter definieren (2)


“:” startet die Definition,

quadrat ist der Name des neuen Forth Wortes.

Der Kommentar beschreibt den Stack-Effekt

Die Worte "dup *" werden nicht ausgeführt, sondern in die Definition hineincompiliert.

		: quadrat ( n -- n^2 ) dup * ; 
		
	

Wörter definieren (3)


Das neu definierte Wort kann man genauso verwenden wie ein “eingebautes” Wort, man kann es natürlich auch in weitere Definitionen einbauen:

		: zur-dritten ( n -- n^3 ) dup quadrat * ;
		
		-5 zur-dritten .
		
		: zur-vierten ( n -- n^4 ) quadrat quadrat ;
		
		3 zur-vierten .
		
	

Wörter umdefinieren


Neue Wörter mit Namen von bestehenden Wörtern überlagern die bestehenden.

Neue Definitionen benutzen die neuen Wörter, schon eingebaute benutzen weiterhin die alte Definition.

		: * + ; 
		
		5 quadrat . [RTN] 25
		
		5 5 * . [RTN] 10
		
	

WORDS


listet alle Wörter, die Forth kennt, sortiert von jüngsten zu den ältesten Definitionen

der Befehl heisst in FIG-FORTH/FORTH-77/79 Systemen "VLIST"

		WORDS ( -- )
	

FORGET


FORGET ccc ( -- )

löscht die Definition von “ccc” und alle Definitionen, die nach “ccc” definiert wurden! Redefinierte Wörter werden wieder sichtbar.

		FORGET * 
		5 5 * . [RTN] 25
	

Constant


CONSTANT ccc ( n -- )

definiert ein Konstanten-Wort mit dem Namen “ccc” und dem Wert “n”

wird die neue Konstante als Wort benutzt, legt sie ihren Wert auf den Stack

		12 CONSTANT DUTZEND [RTN] 
		DUTZEND ( -- 12 )
	

Variable


VARIABLE ccc ( -- ) ( F83/ANSI Forth )

definiert eine Variable mit dem Namen “ccc”, oder


VARIABLE ccc ( n -- ) ( FIG/F79 Forth )

definiert eine Variable mit dem Namen “ccc” und dem Wert “n”

Variable (2)


		VARIABLE BETRAG [RTN] 
		BETRAG ( -- addr )
		

legt die Speicheradresse der Variable auf den Stack

! (STORE)


		! ( x addr -- )
		

schreibe den Wert x in die Speicherstelle mit Adresse “addr”


		200 BETRAG !
		

speichert den Wert 200 in die Variable “BETRAG”

@ (FETCH)


		@ ( addr -- x )
		

legt den in der Speicherstelle “addr” gepeicherten Wert auf den Stack


		BETRAG @ . [RTN] 200
		

liest den Wert der Variable “BETRAG” und gibt den Wert am Bildschirm aus

+! (PLUS-STORE)


		+! ( n addr -- )
		

addiert den Wert “n” zum Wert in der Speicherstelle “addr”


		10 BETRAG +!
		

Speicherzugriff


@, !, +! funktionieren mit Variablen aber auch mit jeder anderen Speicherstelle sie sind die Forth-Entsprechung für (Basic) “PEEK” und “POKE”

Kontrollstrukturen


Kontrollstrukturen können in Forth nur in Definitionen verwendet werden (nicht im interaktiven Modus). Eine IF-Struktur sieht so aus:

		: abs ( n1 -- +n2 ) 
			dup 0 < if
				negate then ;
		5 abs . 
		-5 abs .
	

Kontrollstrukturen (2)


IF nimmt ein Flag vom Stack. Ist es ungleich 0 ("wahr"), wird der folgende Code ausgeführt, ansonsten zum zugehörigen THEN (oder ELSE) gesprungen.

“<” vergleicht die beiden obersten Stackelemente und produziert ein Flag:

		1 2 < . 
		2 1 < . 
		1 1 < .
	

Kontrollstrukturen (3)


weitere Vergleichsworte sind =, >, <>, <=, >= (nicht alle Kombinationen aus Typen und Vergleichsworten sind Standard Forth Wörter, können aber bei Bedarf einfach erzeugt werden).

Kontrollstrukturen (4)


Optional kann man auch einen ELSE-Abschnitt verwenden:

		: min ( n1 n2 -- n ) 
			2dup < if
				drop 
			else
				nip 
			then ;
	

Anmerkung: Der Stackkommentar von 2dup ist

	( n1 n2 -- n1 n2 n1 n2 )
	

Logische Operatoren


Ein true-Flag hat alle bits gesetzt, false keines (F83/ANSI Forth):

	hex true u. decimal true . false .
	

Anmerkung: in FORTH77/79 und FIG-Forth ist true "1"

Anmerkung: jede Zahl ungleich "0" wird als logischtrue interpretiert

Logische Operatoren (2)


Zum Verknüpfen von Flags kann man die Wörter AND, OR, XOR und 0= und INVERT verwenden. Dabei arbeiten AND, OR, XOR, und INVERT bitweise, produzieren also nur aus wohlgeformten Flags wieder neue gültige Flags:

	1 2 and . 
	1 2 or . 
	1 3 xor . 
	1 invert .
	

Logische Operatoren (3)


0= dagegen nimmt beliebige Zahlen als Eingabe und produziert ein Flag.

	1 0= .
	

Um aus einer Zahl ein wohlgeformtes Flag zu machen, verwendet man 0<>:

	1 0<> .
	

Logische Operatoren (4)


Die Eigenschaft "alle bits gesetzt" kann man verwenden, um IFs zu vermeiden:

	: foo ( n1 -- n2 ) 0= if 14 else 0 then ; 
	0 foo . 
	1 foo .
	

Ohne IF

	: foo ( n1 -- n2 ) 0= 14 and ; 
	0 foo . 
	1 foo .
	

Schleifen


Die einfachste Schleife ist die Endlosschleife:

		: endless ( -- ) 
		  0 begin
		    dup . 1+ 
		again ;
		
		endless
	

BEGIN macht nichts (zur Laufzeit), AGAIN springt zurueck zum BEGIN.

Schleifen (2)


Eine Schleife mit einer Ausstiegsbedingung an beliebiger Stelle sieht so aus:

		: log2 ( +n1 -- n2 )
		 2 / 0 begin
		    over 0> 
		 while
		    1+ swap 2 / swap 
		repeat nip ;
		
		7 log2 . 
		8 log2 .
	

WHILE konsumiert ein Flag; ist es gleich 0 (falsch), wird hinter dem REPEAT fortgesetzt. REPEAT springt zurück zum BEGIN, wie AGAIN.

Schleifen (3)


Und hier ist eine Schleife mit Ausstieg am Ende:

		: log2 ( +n1 -- n2 ) 
		-1 begin
		  1+ swap 2 / swap
		  over 0 <= until
		nip ;
	

UNTIL konsumiert ein Flag; ist es wahr (<>0), wird die Schleife verlassen.

Schleifen (4)


?DO nimmt zwei Zahlen vom stack ( n1 n2 -- ), und die Schleife zwischen ?DO und LOOP wird dann n1-n2 mal ausgeführt. Auf den Zähler kann man mit I zugreifen:

		: fac ( n -- n! ) 
		  1 swap 1+ 1 ?do
		    i * 
		  loop ;
		
		5 fac . 
		
		7 fac .
	

Returnstack


Neben dem normalen Stack (dem Daten-Stack) gibt es in Forth den Return-Stack, der vor allem dazu dient, die Rücksprungadressen bei Definitionsaufrufen zu speichern.

Returnstack (2)


Dieser Stack ist auch für Programmierer zugänglich:

		: foo ( n1 n2 -- ) 
		.s >r .s 
		r@ . 
		>r .s
		r@ . r> .
		r@ . r> . ; 
		
		1 2 foo
	

>R schiebt also ein Element vom Daten- auf den Return-Stack, R> umgekehrt, und R@ kopiert das oberste Return-Stack-Element auf den Datenstack.

Returnstack (3)


Der Returnstack wird dazu verwendet, Daten zwischenzuspeichern, wenn eine alleinige Speicherung auf dem Datenstack zu kompliziert ist:

		: 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 ) 
		  rot >r rot r> ;
	

Da die Rücksprungadresse und die Schleifenkontrollparameter von Zählschleifen auf dem Returnstack liegen, müssen alle Elemente, die in einer Definition bzw. Zählschleife auf den Returnstack geschoben werden, vor dem Ende der Definition bzw. Zählschleifen wieder entfernt werden.

Elemente, die ausserhalb auf den Return-Stack geschoben wurden, können in der Definition bzw. Zählschleife nicht verwendet werden. Wenn man sich beim Return- Stack verzählt, endet das meistens in einem Crash:

		: crash ( n -- ) >r ;
		5 crash
	

Speicher


Speicher kann reserviert werden mit:

		create speicher 20 cells allot
	

Dies erzeugt ein Wort “speicher”, welches bei der Ausführung eine Adresse liefert, und reserviert an dieser Adresse Platz für 20 Zellen.

Speicher (2)


Mittels Adressarithmetik können wir auf einzelne Elemente zugreifen:

		3 speicher 5 cells + !
	

Das Wort "cells" definiert die Wortgroesse der CPU und des Forth Systems

		: cells 2 * ;  ( 8/16 bit CPU )
		: cells 4 * ;  ( 32bit CPU )
		: cells 8 * ;  ( 64bit CPU )
	

Speicher (3)


Mit "," kann man Speicher reservieren und initialisieren:

		create v3 
		 5 , 4 , 3 , 2 , 1 ,
		v3 @ . 
		v3 1 cells + @ . 
		v3 2 cells + @ .
	

Speicher (4)


, ( n -- )

reserviert Platz für eine Zelle im Speicher, nimmt einen Wert vom Stack und speichert diesen Wert im reservierten Speicher

c, ( 8b -- )

speichert ein Byte statt eine Zelle

Speicher (5)


Man kann natürlich auch Speicher reservieren, ohne eine neues Wort zu produzieren:

here 10 cells allot .s

HERE liefert dabei die Anfangsadresse des Speichers, die man möglichst irgendwo abspeichern sollte (z.B. in einer Variable), sonst findet man den Bereich nicht wieder.

Speicher (6)


Der mit ALLOT verwaltete Speicher kommt aus dem Dictionary (das auch Wörter speichert) und wird als Stack verwaltet; mit

-10 cells allot

können die letzten 10 angelegten Zellen wieder freigegeben werden.

Speicher (7)


CREATE ccc

legt ein neues Wort "ccc" im Speicher an, ohne weiteren Speicher zu reservierten

Zur Laufzeit legt das neue Wort "ccc" die Addresse auf den Stapel, welche direkt dem Wort im Speicher nachfolgt

Der Programmierer kann per ALLOT einen beliebig grossen Speicher nach dem Wort reservieren

CREATE kann benutzt werden, um Speicherstellen per Name ansprechen zu können

Speicher (8)


Beispiel für CREATE und ALLOT:

CREATE tabelle 1024 ALLOT

Dies reserviert an der Speicherstelle, welche durch das neue Wort "tabelle" bereitgestellt wird, 1024 Byte

ʻ (TICK)


‘ ccc ( -- xt )

sucht Forth-Wort “ccc” und legt das “execution token (xt)” auf den Stapel

execute ( xt -- ?? )

führt das Wort, auf das der “xt” zeigt, aus. In Wort-Definitionen wird das Wort ['] verwendet.

recursion


das Forth-Wort recursive (in einigen System auch "recurse". "self" oder "myself" genannt) ruft das aktuell definiert Wort rekursiv auf

	
		: fib1 ( n1 -- n2 )
		    dup 2 < if drop 1 exit then
		    dup  1- recursive 
		    swap 2- recursive  + ;

PAUSE!



Forth Kerne

Forth Kerne

Wir schauen und die Implementation verschiedener Forth System anhand des Wortes "square" an


		: SQUARE  DUP * ;
	

Forth Kerne - ITC

Indirect Threaded Code

wird in den meisten Forth Implementationen benutzt

guter Kompromiss zwischen Speicherverbrauch und Geschwindigkeit


Grafik aus Moving Forth, Part 1

Forth Kerne - DTC

Direct Threaded Code

wird in einigen Forth Implementationen benutzt

kann schneller sein als ITC oder STC


Grafik aus Moving Forth, Part 1

Forth Kerne - STC

Subroutine Threaded Code

jedes Forth Wort ist ein nativer Subroutine Aufruf (JMP oder CALL)


Grafik aus Moving Forth, Part 1

Forth Kerne - TTC

Token Threaded Code

sehr speicherplatzsparend

Programm ist relozierbar und prozessorabhaengig (Bytecode)

langsam, da weitere Indirektion


Grafik aus Moving Forth, Part 1

Forth Kerne - Native Code

Native Code

kein Threading

Forth compiler erzeugt direkten Maschinencode

Forth Benchmarks - Integer

Integer Benchmark


		32000 constant intMax    variable intResult
		: DoInt ( -- )
		  1 dup intResult dup >r !
		  begin  dup intMax <
		  while
		    dup negate r@ +! 1+    dup r@ +! 1+
		    r@ @ over * r@ ! 1+    r@ @ over / r@ ! 1+
		  repeat 
		  r> drop drop ;
	

Forth Benchmarks - Fibonacci 1

Fibonacci Benchmark (recursiv)


		: fib1 ( n1 -- n2 )
		    dup 2 < if drop 1 exit then
		    dup  1- recursive 
		    swap 2- recursive  + ;

		: fib1-bench 1000 0 do
		     10 0 do i fib1 drop loop
		  loop ;
	

Forth Benchmarks - Fibonacci 2

Fibonacci Benchmark (iterativ)


		: fib2 ( n1 -- n2 )                                                                
		   0 1 rot 0 ?do 
		      over + swap loop 
		   drop ;
		
		: fib2-bench 10000 0 do i fib2 drop loop ;
	

Forth Benchmarks - Nesting

Nesting Benchmark


		\ Forth nesting (NEXT) Benchmark                                        
		: bottom ;                                                                         
		: 1st bottom bottom ;  : 2nd 1st 1st ;      : 3rd 2nd 2nd ;                        
		: 4th 3rd 3rd ;        : 5th 4th 4th ;      : 6th 5th 5th ;                        
		: 7th 6th 6th ;        : 8th 7th 7th ;      : 9th 8th 8th ;                        
		: 10th 9th 9th ;       : 11th 10th 10th ;   : 12th 11th 11th ;                     
		: 13th 12th 12th ;     : 14th 13th 13th ;   : 15th 14th 14th ;                     
		: 16th 15th 15th ;     : 17th 16th 16th ;   : 18th 17th 17th ;                     
		: 19th 18th 18th ;     : 20th 19th 19th ;   : 21th 20th 20th ;                     
		: 22th 21th 21th ;     : 23th 22th 22th ;   : 24th 23th 23th ;                     
		: 25th 24th 24th ;                                                                 

		: 32million   CR ." 32 million nest/unnest operations" 25th ;                      
		:  1million   CR ."  1 million nest/unnest operations" 20th ;
	

Forth Benchmarks - Memory Move

Memory Move Benchmark


		\ Forth Memory Move Benchmark                       cas 20101204                   
		  8192 CONSTANT bufsize                                                             
		 VARIABLE buf1 HERE bufsize 1+ allot BUF1 !                                         
		 VARIABLE buf2 HERE bufsize 1+ allot BUF2 !                                                                                                                       
		 : test-CMOVE 49 0 DO BUF1 @ BUF2 @ bufsize CMOVE LOOP ;                                                                                                                
		 : test-CMOVE> 49 0 DO BUF2 @ BUF1 @ bufsize CMOVE> LOOP ;                                                                                                              
		 : test-MOVE> 49 0 DO BUF1 @ BUF2 @ bufsize MOVE LOOP ;                                                                                                                 
		 : test-<MOVE 49 0 DO BUF2 @ BUF1 @ bufsize MOVE LOOP ;      
		 : move-bench test-CMOVE test-CMOVE> test-MOVE> test-<MOVE ;
	

Forth Benchmarks - Count Bits

Count Bits Benchmark


		\ Forth Benchmark - count bits in byte              
		VARIABLE cnt
		 : countbits ( uu -- #bits )
		   cnt off
		   8 0 DO dup $01010101  and cnt +! 2/ LOOP drop
		   0 cnt 4 bounds DO i C@ + LOOP ;
		
		 : count-bits 8192 DO I countbits . LOOP ;
	

Forth Benchmarks - Sieve

Sieve Benchmark


		8192 CONSTANT SIZE   VARIABLE FLAGS  0 FLAGS !  
		SIZE ALLOT                         
	    : DO-PRIME ( -- )                                                                        
		   FLAGS SIZE 1 FILL  ( set array )                                                 
		   0 ( 0 COUNT ) SIZE 0                                                             
		   DO FLAGS I + C@                                                                  
		     IF I DUP + 3 + DUP I +                                                         
		        BEGIN DUP SIZE <                                                            
		        WHILE 0   OVER FLAGS +  C!  
		        OVER +  REPEAT                                  
		        DROP DROP 1+                                                                
		     THEN                                                                           
		 LOOP                                                                               
		 . ." Primes" CR ;
	

Forth Benchmarks - GCD 1

GCD (Greatest Common Divisor) Benchmark


		 : gcd1 ( a b -- gcd )                                                               
		   OVER IF                                                                          
		     BEGIN                                                                          
		       DUP WHILE                                                                    
		          2DUP U> IF SWAP THEN OVER -                                               
		     REPEAT DROP ELSE                                                               
		     DUP IF NIP ELSE 2DROP 1 THEN                                                   
		   THEN ;  

		: gcd1-bench 100 0 DO 
		      100 0 DO j i gcd1 drop loop
		  loop ;
	

Forth Benchmarks - GCD 2

GCD (Greatest Common Divisor) Benchmark


		: gcd2 ( a b -- gcd )                                                              
		   2DUP        D0= IF  2DROP 1 EXIT   THEN                                          
		   DUP          0= IF   DROP   EXIT   THEN                                          
		   SWAP DUP     0= IF   DROP   EXIT   THEN                                          
		   BEGIN  2DUP -                                                                    
		   WHILE  2DUP < IF OVER -                                                          
		                 ELSE SWAP OVER - SWAP                                              
		                 THEN                                                               
		   REPEAT NIP ;          

		: gcd2-bench 100 0 DO 
		      100 0 DO j i gcd2 drop loop
		  loop ;
	

Forth Benchmarks - Takeuchi

Takeuchi Benchmark


		: 3dup 2 pick 2 pick 2 pick ;                                                        
		: tak ( x y z -- t )                                                                 
		   over 3 pick < NEGATE IF nip nip exit then                                          
		   3dup rot 1- -rot recursive >r                                                      
		   3dup swap 1- -rot swap recursive >r                                                
		             1- -rot recursive                                                        
		   r> swap r> -rot recursive ;                                                        

		 : takbench ( -- )                                                                    
		   0 10000 0 DO DROP 18 12 6 tak LOOP ;
	

Forth Benchmarks - 6502emu

6502emu Benchmark


		\ A simple 6502 emulattion benchmark                         cas                     
		\ only 11 opcodes are implemented. The memory layout is:                             
		\  2kB RAM at 0000-07FF, mirrored throughout 0800-7FFF                               
		\ 16kB ROM at 8000-BFFF, mirrored at C000                                            
		decimal                                                                              
		create ram 2048 allot   : >ram $7FF  and ram + ;                                     
		create rom 16384 allot  : >rom $3FFF and rom + ;                                     
		\ 6502 registers                                                                     
		variable reg-a   variable reg-x  variable reg-y                                      
		variable reg-s   variable reg-pc  : reg-pc+ reg-pc +! ;                              
		\ 6502 flags                                                                         
		variable flag-c  variable flag-n   variable cycle                                    
		variable flag-z  variable flag-v  : cycle+ cycle +! ;                                
		hex ....
	

Forth Benchmarks - benchme

Benchmark Helper


		: beep ( -- ) \ emits an audible beep signal
		  7 con! ;    \ this is hardware and implementation dependent

		: benchme ( xt n -- )    \ executes the word with the execution token 'xt' n-times
		  dup >r                 \ save number of iterations
		  beep                   \ signal of benchmark start
		  0 do dup execute loop  \ execute word. word must have a neutral stack effect
		  beep                   \ signal benchmark end
		  cr r> . ." Iterations." cr \ emit message
		;

		\ Example: ' fib1-bench 100 benchme
		\ this will execute the Fibonacci 1 benchmark 100 times
	

Forth Benchmarks - Regeln

Benchmark Regeln


Jeder VCFe Teilnehmer kann Teil- oder Komplettergebnisse einreichen

Forth Benchmarks - Regeln

Benchmark Regeln


jeder Teilnehmer kann beliebig viele verschiedene Einreichungen vornehmen

Forth Benchmarks - Regeln

Benchmark Regeln


Jede neue Kombination von CPU/Rechner, Taktfrequenz/Betriebsmodus und Forth-System ist als Einreichung möglich

Forth Benchmarks - Regeln

Benchmark Regeln


Jede Einreichung muß von einer Beschreibung der verwendeten Umgebung (CPU/Rechner/Modus/Forth-System) begleitet werden

Forth Benchmarks - Regeln

Benchmark Regeln


Die verwendete Umgebung muß auf dem VCFe präsent sein. Ausnahmen können in begründeten Fällen von der Wettbewerbsleitung gemacht werden

Forth Benchmarks - Regeln

Benchmark Regeln


Eine Einreichung muß für mindestens 3 (Drei) der Benchmarks ein vollständige Ergebniss beinhalten

Forth Benchmarks - Regeln

Benchmark Regeln


Sind die Ergebnisse hochgerechnet, so mussen der Rechenweg und die Zwischenschritte dokumentiert werden

Forth Benchmarks - Regeln

Benchmark Regeln


Die Wettbewerbsleitung entscheidet endgültig welche Einreichungen angenommen werden

Forth Benchmarks - Regeln

Benchmark Regeln


Für jede angenommene Einreichung wird ein Los vergeben

Forth Benchmarks - Regeln

Benchmark Regeln


Aus allen Losen werden am Ende des Wettbewerbs die Preisträger gezogen

Forth Benchmarks - Regeln

Benchmark Regeln


Die Preise sind direkt auf dem VCFe entgegenzunehmen. Ein späterer Versand erfolgt nicht

Forth Benchmarks - Preise

Benchmark Wettbewerb Preise

Fragen?