Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #44905

Re: Ruby/Forth challenge for WJ

From mhx@iae.nl (Marcel Hendrix)
Subject Re: Ruby/Forth challenge for WJ
Newsgroups comp.lang.forth
Message-ID <78599219028399@frunobulax.edu> (permalink)
Date 2016-01-16 11:44 +0200
References <2016Jan15.172237@mips.complang.tuwien.ac.at>
Organization SunSITE.dk - Supporting Open source

Show all headers | View raw


anton@mips.complang.tuwien.ac.at (Anton Ertl) writes Re: Ruby/Forth challenge 
>mhx@iae.nl writes:
[..]
>>I tried pre-filling "memory" with '1': no change.
>>I allotted 256MB at HERE instead of ALLOCATE: no change.
> If you fill everything with the same byte, you have the same kind of
> recurrence in the instruction at $0122462C, and of course you get the
> same result.

> Here I have a version that initializes the array in a way that should
> reduce this effect:

> create counts 256 cells allot
> 256 1024 * 1024 * constant a-size
> a-size allocate throw constant a
> : init-a ( -- )
>  a a-size bounds ?do
>    $00204060 i ! $80a0c0e0 i cell+ !
>  2 cells +loop ;
> : do-test 
>   a a-size bounds ?do
>    1 counts i c@ cells + +!
>  loop ;
> init-a
> do-test

[..]

> With random data, do-test performance should be close to the
> performance of using this initialization; but better measure this:
> AFAIK there a hardware predictor that predicts whether a load is
> independent of a previous store, and this might be a case where its
> performance and the performance of the fallback (what is done when it
> predicts independence, but there actually is a dependence) may be
> relevant.

The result of pattern pre-filling is as follows:

: do-test 
  CR TIMER-RESET
    a a-size bounds ?do
      1 counts i c@ cells + +!
    loop 
  ." \ 0: " .ELAPSED ; do-test
\ 0: 0.459 seconds elapsed. ok

As expected, in high-level it makes no difference.

I dropped to Forth assembler as the problem became
too tedious otherways. The following does in 
assembly language what I tried to express in Forth:

CODE (do-test1) ( -- )
	a-size d# -> rcx mov,
	a d# -> rax mov, 
	BEGIN,
	  [rax] byte -> rdx movzx, 
	  rax inc, 
	  1 b# -> [_ +rdx *8 counts +] qword add,
	  1 b# -> rcx sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  

: do-test 
  CR TIMER-RESET
    (do-test1)
  ." \ 3: " .ELAPSED ; 
\ 3: 0.142 seconds elapsed.

... and this shows that your analysis is fully correct,
we get a run-time as fast as gcc accomplished.

I tried unrolling the loop -- it made no difference.
I removed your initialization -- the run-time dropped
back to 415 ms, as expected.

This means that we should try to minimize certain types
of memory access. The high-level Forth has the same
machine code as shown above, but it additionally 
decrements a stack variable, increasing the run-time 
by a factor of 3. Very annoying in the context of 
Forth. 

It is interesting that the effects of a) not 
initializing and b) having a stack variable do 
not add up. Either one causes the 3 times 
slowdown, having both does not give a 6 times 
slow-down.
I did some more experiments that simply
increment a variable in different locations.

First the straightforward one: keep it in a 
register. As expected this is fast (but
not unbeatable, see (do-count10)).

CODE (do-count1) ( -- ) \ fast!
	a-size d# -> rcx mov,
	BEGIN,
	  1 b# -> rcx sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  
\ count1  : 0.069 seconds elapsed.


The next one is very strange. The
variable is kept in the counts array. After the
memory decrement a variable amount of NOPs
is added and the run-speed is measured. 
At 10 NOPs there is a sweet point: 280 ms. 
It's too slow to be of real interest.
Maybe this indicates problems with jump 
prediction.

: NOPS, ( u -- ) 0 ?DO $90 C, LOOP ;

CODE (do-count2) ( -- ) \ slow
    counts d# -> rax  mov,
    a-size d# -> [rax] mov,
    BEGIN,
	1 b# -> [rax] sub,
	#10 NOPS,
\		\ no nops: 519 ms
\	nop, 	\ 517 ms
\	nop, 	\ 464 ms
\	nop, 	\ 517 ms
\	nop, 	\ 492 ms
\	nop, 	\ 418 ms
\	nop, 	\ 417 ms
\	nop, 	\ 415 ms
\ 	nop, 	\ 452 ms
\ 	nop, 	\ 439 ms
\	nop, 	\ 280 ms
\	nop, 	\ 284 ms
\	nop,  	\ 295 ms
\ 	nop, 	\ 299 ms
\	nop, 	\ 415 ms
\	nop, 	\ 394 ms
\	nop,  	\ 346 ms
\ 	nop, 	\ 358 ms
\	nop, 	\ 422 ms
\	nop, 	\ 420 ms
\	nop,  	\ 415 ms
\ 	nop, 	\ 419 ms
\	nop, 	\ 483 ms
\	nop, 	\ 486 ms
\	nop,  	\ 486 ms
\ 	nop, 	\ 490 ms
\	nop, 	\ 555 ms
\	nop, 	\ 555 ms
\	nop,  	\ 567 ms
\	32 nops 0.696 s
\ 	64 nops 1.256 s
	0=, 
    UNTIL,
    rbx jmp,
END-CODE  
\ count2  : 0.280 seconds elapsed.

Next I put the variable in the Forth return stack.
I was relieved to see that this is not very much 
worse than other locations (read on). My fear
that executable stack memory pages are worse than
R/W ones appears not be true.

CODE (do-count3) ( -- ) \ slow
	a-size d# -> [rbp -8 +] mov,
	BEGIN,
	  1 b# -> [rbp -8 +] sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  
\ count3  : 0.516 seconds elapsed.


This one just tries a different sequence 
(than do-count3) to update the stack variable. 
It is all the same to the CPU.

CODE (do-count4) ( -- )
	a-size d# -> [rbp -8 +] mov,
    	BEGIN,
          [rbp -8 +] -> rax mov,
	  1 b# -> rax sub,
	  rax -> [rbp -8 +] mov, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  
\ count4  : 0.511 seconds elapsed.

This shows yet another sequence. Don't
bother, the CPU couldn't care less.

CODE (do-count5) ( -- )
	[rbp -8 +] -> rcx  lea,
	a-size d# -> [rcx] mov,
    	BEGIN,
          [rcx] -> rax mov,
	  1 b#  -> rax sub,
	  rax   -> [rcx] mov,  0=, 
	UNTIL,
	rbx jmp,
END-CODE  
\ count5  : 0.510 seconds elapsed.

SIB addressing: it is as fast as the 
old stuff, the CPU doesn't mind (any more).

CODE (do-count6) ( -- )
	a-size d# -> [_ counts +] mov,
    BEGIN,
        1 b# -> [_ counts +] sub,
0=, UNTIL,
	rbx jmp,
END-CODE  
\ count5  : 0.510 seconds elapsed.

Very conventional: no change.

CODE (do-count7) ( -- )
	a-size d# -> counts offset mov,
    	BEGIN,
          1 b# -> counts offset sub, 0=, 
        UNTIL,
	rbx jmp,
END-CODE  
\ count5  : 0.524 seconds elapsed.

This is a variant of (do-count2). It is
a bit faster although it has two jumps.
Being faster might also be because it is
assembled at a different memory address.

CODE (do-count8a) ( -- ) \ has 2 jumps
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  1 b# -> [rax] sub,  0<>,
	WHILE,	
	REPEAT,
	rbx jmp,
END-CODE  
\ count8a : 0.425 seconds elapsed.


Spreading out the code, worse.

CODE (do-count8b) ( -- ) \ has 2 jumps and extra fetch
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  0 b# -> [rax] cmp, 0<>,
	WHILE,	
	  1 b# -> [rax] sub, 
	REPEAT,
	rbx jmp,
END-CODE  
\ count8b : 0.475 seconds elapsed.

Deliberately bad code. The CPU couldn't care less.

CODE (do-count8c) ( -- ) \ has 2 jumps and 2 extra fetches
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  [rax] -> rcx mov, 
	  0 b# -> [rax] cmp, 0<>,
	WHILE,	
	  1 b# -> [rax] sub, 
	REPEAT,
	rbx jmp,
END-CODE  
\ count8c : 0.500 seconds elapsed.

The fact that the variable is in a 
register does not mean that jumps 
are free (see (do-count1) which only has
a single jump and is twice faster).

CODE (do-count8d) ( -- ) \ fast!
	a-size d# -> rax mov,
	BEGIN,
	  rax -> rax or, 0<>,
	WHILE,	
	  [rax -1 +] -> rax lea, 
	REPEAT,
	rbx jmp,
END-CODE  
\ count8d : 0.138 seconds elapsed.

This shows that loop unrolling is effective, 
so even the single jump is costly.
Note that we try to prevent hitting the
same memory location here.

CODE (do-count9) ( -- ) 
	counts d#     -> rax mov,
	a-size 8 / d# -> rcx mov,
	rcx  -> [rax   0 +] mov,
	rcx  -> [rax   8 +] mov,
	rcx  -> [rax #16 +] mov,
	rcx  -> [rax #24 +] mov,
	rcx  -> [rax #32 +] mov,
	rcx  -> [rax #40 +] mov,
	rcx  -> [rax #48 +] mov,
	rcx  -> [rax #56 +] mov,
	BEGIN,
	  1 b# -> [rax   0 +] sub,
	  1 b# -> [rax   8 +] sub,
	  1 b# -> [rax #16 +] sub,
	  1 b# -> [rax #24 +] sub,
	  1 b# -> [rax #32 +] sub,
	  1 b# -> [rax #40 +] sub,
	  1 b# -> [rax #48 +] sub,
	  1 b# -> [rax #56 +] sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  
\ count9  : 0.069 seconds elapsed.

Hitting the same memory location is
not the problem ((do-count9)), it appears 
that the jump is eating the time. This
variant is faster than count9 because it
only has one jump.

CODE (do-count10) ( -- ) 
	counts d# -> rax mov,
	a-size 8 / d# -> rcx mov,
	rcx -> [rax 0 +] mov,
    BEGIN,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
0=, UNTIL,
	rbx jmp,
END-CODE  
\ count10 : 0.054 seconds elapsed.


I think that this exercise proves that

1) The stack is not different from the
dictionary or allocated memory (for variable
storage).

2) Hitting the same memory location all of the
time is not a problem (it happens a lot in
many programs so it may have received close
engineering attention). What hurts is tight
loops. Tight loops must be unrolled not because
it makes code faster, but because not
unrolling makes the code slower :-)

3) R-M-W code sequences should get special
attention, as Anton's analysis (verified by 
experiment) shows. The solution is not 
necessarily to keep everything in registers
all of the time, as the do-count exercise
shows. 

Comments invited.

-marcel

-- full source code, needs hand editing ----------

ANEW -strangefruit

NEEDS -assemble

HERE #256 cells allot =: counts
#256 #1024 * #1024 * constant a-size
a-size allocate ?allocate =: a

: init-a ( -- )
  a a-size bounds ?do
    $0020406080a0c0e0 i ! $1030507090b0d0f0 i cell+ !
  2 cells +loop ;

init-a FORGET init-a



0 [IF]

: do-test 
  CR TIMER-RESET
    a a-size bounds ?do
      1 counts i c@ cells + +!
    loop 
  ." \ 0: " .ELAPSED ; do-test

[THEN]

0 [IF]

: do-test 
  CR TIMER-RESET
    a  a-size 1- FOR  C@+  counts []CELL  1 swap +!  NEXT  DROP  
  ." \ 1: " .ELAPSED ; do-test

[THEN]

0 [IF]

: do-test 
  CR TIMER-RESET
    a a-size
    BEGIN  DUP 1- SWAP
    WHILE  SWAP  C@+  counts []CELL  1 swap +!  SWAP 
    REPEAT
    2DROP
  ." \ 2: " .ELAPSED ; do-test

[THEN]

1 [IF]

CODE (do-count1) ( -- ) \ fast!
	a-size d# -> rcx mov,
	BEGIN,
	  1 b# -> rcx sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  

: NOPS, ( u -- ) 0 ?DO $90 C, LOOP ;

CODE (do-count2) ( -- ) \ slow
    counts d# -> rax  mov,
    a-size d# -> [rax] mov,
    BEGIN,
	1 b# -> [rax] sub,
	1 NOPS,
\		\ no nops: 519 ms
\	nop, 	\ 517 ms
\	nop, 	\ 464 ms
\	nop, 	\ 517 ms
\	nop, 	\ 492 ms
\	nop, 	\ 418 ms
\	nop, 	\ 417 ms
\	nop, 	\ 415 ms
\ 	nop, 	\ 452 ms
\ 	nop, 	\ 439 ms
\	nop, 	\ 280 ms
\	nop, 	\ 284 ms
\	nop,  	\ 295 ms
\ 	nop, 	\ 299 ms
\	nop, 	\ 415 ms
\	nop, 	\ 394 ms
\	nop,  	\ 346 ms
\ 	nop, 	\ 358 ms
\	nop, 	\ 422 ms
\	nop, 	\ 420 ms
\	nop,  	\ 415 ms
\ 	nop, 	\ 419 ms
\	nop, 	\ 483 ms
\	nop, 	\ 486 ms
\	nop,  	\ 486 ms
\ 	nop, 	\ 490 ms
\	nop, 	\ 555 ms
\	nop, 	\ 555 ms
\	nop,  	\ 567 ms
\	32 nops 0.696 s
\ 	64 nops 1.256 s
	0=, 
    UNTIL,
    rbx jmp,
END-CODE  

CODE (do-count3) ( -- ) \ slow
	a-size d# -> [rbp -8 +] mov,
	BEGIN,
	  1 b# -> [rbp -8 +] sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count4) ( -- )
	a-size d# -> [rbp -8 +] mov,
    	BEGIN,
          [rbp -8 +] -> rax mov,
	  1 b# -> rax sub,
	  rax -> [rbp -8 +] mov, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count5) ( -- )
	[rbp -8 +] -> rcx  lea,
	a-size d# -> [rcx] mov,
    	BEGIN,
          [rcx] -> rax mov,
	  1 b#  -> rax sub,
	  rax   -> [rcx] mov,  0=, 
	UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count6) ( -- )
	a-size d# -> [_ counts +] mov,
    BEGIN,
        1 b# -> [_ counts +] sub,
0=, UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count7) ( -- )
	a-size d# -> counts offset mov,
    	BEGIN,
          1 b# -> counts offset sub, 0=, 
        UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count8a) ( -- ) \ has 2 jumps, slow but not slower
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  1 b# -> [rax] sub,  0<>,
	WHILE,	
	REPEAT,
	rbx jmp,
END-CODE  

CODE (do-count8b) ( -- ) \ has 2 jumps and extra fetch, slow but not slower
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  0 b# -> [rax] cmp, 0<>,
	WHILE,	
	  1 b# -> [rax] sub, 
	REPEAT,
	rbx jmp,
END-CODE  

CODE (do-count8c) ( -- ) \ has 2 jumps and 2 extra fetches, bit slower 
	a      d# ->  rax  mov,
	a-size d# -> [rax] mov,
	BEGIN,
	  [rax] -> rcx mov, 
	  0 b# -> [rax] cmp, 0<>,
	WHILE,	
	  1 b# -> [rax] sub, 
	REPEAT,
	rbx jmp,
END-CODE  

CODE (do-count8d) ( -- ) \ has 2 jumps, bit slower 
	a-size d# -> rax mov,
	BEGIN,
	  rax -> rax or, 0<>,
	WHILE,	
	  [rax -1 +] -> rax lea, 
	REPEAT,
	rbx jmp,
END-CODE  

CODE (do-count9) ( -- ) 
	counts d#     -> rax mov,
	a-size 8 / d# -> rcx mov,
	rcx  -> [rax   0 +] mov,
	rcx  -> [rax   8 +] mov,
	rcx  -> [rax #16 +] mov,
	rcx  -> [rax #24 +] mov,
	rcx  -> [rax #32 +] mov,
	rcx  -> [rax #40 +] mov,
	rcx  -> [rax #48 +] mov,
	rcx  -> [rax #56 +] mov,
    BEGIN,
	1 b# -> [rax   0 +] sub,
	1 b# -> [rax   8 +] sub,
	1 b# -> [rax #16 +] sub,
	1 b# -> [rax #24 +] sub,
	1 b# -> [rax #32 +] sub,
	1 b# -> [rax #40 +] sub,
	1 b# -> [rax #48 +] sub,
	1 b# -> [rax #56 +] sub,
0=, UNTIL,
	rbx jmp,
END-CODE  

CODE (do-count10) ( -- ) 
	counts d# -> rax mov,
	a-size 8 / d# -> rcx mov,
	rcx -> [rax 0 +] mov,
    BEGIN,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
	1 b# -> [rax] sub,
0=, UNTIL,
	rbx jmp,
END-CODE  

CODE (do-test1) ( -- )
	a-size d# -> rcx mov,
	a d# -> rax mov, 
	BEGIN,
	  [rax] byte -> rdx movzx, rax inc, 1 b# -> [_ +rdx *8 counts +] qword add,
	  1 b# -> rcx sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  

CODE (do-test2) ( -- )
	a-size d# -> rcx mov,
	a d# -> rax mov, 
	BEGIN,
	  [rax] byte -> rdx movzx, rax inc,
	  1 b# -> [_ +rdx *8 counts +] qword add,
  	  [rax] byte -> rdx movzx, rax inc, 
  	  1 b# -> [_ +rdx *8 counts +] qword add,
	  2 b# -> rcx sub, 0=, 
	UNTIL,
	rbx jmp,
END-CODE  


: do-test1 
  CR TIMER-RESET
    (do-test1)
  ." \ 3: " .ELAPSED ; do-test1

: do-test2 
  CR TIMER-RESET
    (do-test2)
  ." \ 4: " .ELAPSED ; do-test2

: DO-TESTS
  CR ." \ count1  : " TIMER-RESET  (do-count1)  .ELAPSED	
  CR ." \ count2  : " TIMER-RESET  (do-count2)  .ELAPSED	
  CR ." \ count3  : " TIMER-RESET  (do-count3)  .ELAPSED 
  CR ." \ count4  : " TIMER-RESET  (do-count4)  .ELAPSED 
  CR ." \ count5  : " TIMER-RESET  (do-count5)  .ELAPSED 
  CR ." \ count6  : " TIMER-RESET  (do-count6)  .ELAPSED 
  CR ." \ count7  : " TIMER-RESET  (do-count7)  .ELAPSED 
  CR ." \ count8a : " TIMER-RESET  (do-count8a) .ELAPSED
  CR ." \ count8b : " TIMER-RESET  (do-count8b) .ELAPSED
  CR ." \ count8c : " TIMER-RESET  (do-count8c) .ELAPSED
  CR ." \ count8d : " TIMER-RESET  (do-count8d) .ELAPSED
  CR ." \ count9  : " TIMER-RESET  (do-count9)  .ELAPSED 
  CR ." \ count10 : " TIMER-RESET  (do-count10) .ELAPSED ;

[THEN]

\ 0: 0.459 seconds elapsed.
\ 1: 0.456 seconds elapsed.
\ 2: 0.826 seconds elapsed.
\ 3: 0.142 seconds elapsed.
\ 4: 0.142 seconds elapsed.

\ FORTH> do-tests
\ count1  : 0.072 seconds elapsed.
\ count2  : 0.280 seconds elapsed.
\ count3  : 0.521 seconds elapsed.
\ count4  : 0.486 seconds elapsed.
\ count5  : 0.494 seconds elapsed.
\ count6  : 0.497 seconds elapsed.
\ count7  : 0.523 seconds elapsed.
\ count8a : 0.421 seconds elapsed.
\ count8b : 0.484 seconds elapsed.
\ count8c : 0.494 seconds elapsed.
\ count8d : 0.139 seconds elapsed.
\ count9  : 0.070 seconds elapsed.
\ count10 : 0.056 seconds elapsed.

Back to comp.lang.forth | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 07:47 -0800
  Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-12 16:25 +0000
    Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-12 10:45 -0600
    Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 08:46 -0800
      Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 11:57 -0500
        Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 09:22 -0800
          Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-12 21:04 -0800
            Re: Ruby/Forth challenge for WJ Ron Aaron <rambamist@gmail.com> - 2016-01-13 07:59 +0200
      Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-12 19:42 +0000
        Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 12:53 -0800
    Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-13 15:45 +0000
      Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-13 13:44 -0500
        Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 11:39 -0800
          Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-14 05:01 +0100
          Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 12:28 +0000
  Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 09:50 -0800
  Re: Ruby/Forth challenge for WJ Pablo Hugo Reda <pabloreda@gmail.com> - 2016-01-12 11:50 -0800
  Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 12:30 -0800
  Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 12:43 -0800
    Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-12 21:01 +0000
    Re: Ruby/Forth challenge for WJ peter.m.falth@gmail.com - 2016-01-12 15:00 -0800
      Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 16:13 -0800
        Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-12 16:22 -0800
        Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 16:24 -0800
          Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-12 17:46 -0800
            Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 18:39 -0800
              Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-13 13:05 -0800
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-14 04:33 +0100
                Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-14 03:27 -0800
                Re: Ruby/Forth challenge for WJ peter.m.falth@gmail.com - 2016-01-14 04:42 -0800
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 13:03 +0000
                Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 21:17 -0800
                Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-13 21:44 -0800
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 10:57 +0000
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 12:20 -0800
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 13:57 -0800
                Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-14 14:22 -0800
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 16:14 -0800
                Re: Ruby/Forth challenge for WJ Melzzzzz <mel@zzzzz.com> - 2016-01-15 03:05 +0100
                Re: Ruby/Forth challenge for WJ Waldek Hebisch <hebisch@antispam.uni.wroc.pl> - 2016-01-15 00:41 +0000
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-15 16:22 +0000
                Re: Ruby/Forth challenge for WJ mhx@iae.nl (Marcel Hendrix) - 2016-01-16 11:44 +0200
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-16 04:49 -0800
                Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-16 15:05 +0000
                Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-18 03:26 -0800
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-18 12:48 +0000
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-19 22:26 +0100
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-20 03:05 -0800
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-20 21:00 +0100
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-20 15:57 -0800
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-21 23:02 +0100
                Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-22 01:25 +0000
                Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-21 18:05 -0800
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-21 22:03 -0800
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-20 13:40 +0000
                Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-18 03:55 -0800
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-23 15:13 -0600
                Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-24 00:55 -0800
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 04:48 -0600
                Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-25 12:39 +0000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 08:05 -0600
                Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-25 16:40 +0000
                Re: Ruby/Forth challenge for WJ Mark Wills <markwills1970@gmail.com> - 2016-01-25 04:44 -0800
                Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-25 14:01 +0000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 08:08 -0600
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 11:56 -0600
                Re: Ruby/Forth challenge for WJ "Elizabeth D. Rather" <erather@forth.com> - 2016-01-25 11:12 -1000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 03:33 -0600
                Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 11:09 +0000
                Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 11:06 +0000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 07:45 -0600
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-26 16:46 +0000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 11:16 -0600
                Object-oriented Forth (was: Ruby/Forth challenge for WJ) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-27 14:13 +0000
                Re: Object-oriented Forth Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-27 10:33 -0600
                Re: Object-oriented Forth hughaguilar96@gmail.com - 2016-01-27 08:45 -0800
                Re: Object-oriented Forth Chris Curl <ccurl609@gmail.com> - 2016-01-27 09:14 -0800
                Re: Object-oriented Forth hughaguilar96@gmail.com - 2016-01-29 21:57 -0800
                Re: Object-oriented Forth Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-30 10:58 +0000
                Re: Object-oriented Forth Chris Curl <ccurl609@gmail.com> - 2016-01-30 09:38 -0800
                Re: Object-oriented Forth Coos Haak <chforth@hccnet.nl> - 2016-01-30 20:39 +0100
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-26 15:56 +0100
                Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 20:46 +0000
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-25 22:27 +0100
                Re: Ruby/Forth challenge for WJ Roelf Toxopeus <rt4all@notthis.hetnet.nl> - 2016-01-28 14:20 +0100
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 08:06 -0600
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-28 16:14 +0100
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 10:32 -0600
                Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-28 17:26 +0000
                Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 12:13 -0600
                Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-29 11:07 +0000
                Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-29 21:18 +0100
                Re: Ruby/Forth challenge for WJ Tessa Bonting <tessa.bonting@gmail.com> - 2016-01-16 06:24 -0800
          Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:21 -0500
            Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:36 -0500
            Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 10:33 -0800
              Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-14 01:37 -0500
  Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 13:45 -0800
  Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 13:55 -0800
    Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 14:34 -0800
    Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 19:00 -0500
      Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 16:49 -0800
        Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 22:18 -0500
  Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-12 14:31 -0800
    Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 16:05 -0800
  Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-01-13 07:58 +0000
    Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:17 -0500
      Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 12:36 -0800
        Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-13 12:53 -0800
        Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-14 06:50 -0600
    Re: Ruby/Forth challenge for WJ Julian Fondren <julian.fondren@gmail.com> - 2016-01-13 05:36 -0800
    Re: Ruby/Forth challenge for WJ lehs <skydda.barnen@gmail.com> - 2016-01-13 11:59 -0800
    Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-21 21:08 -0800
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:36 +0000
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:48 +0000
      Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-02-09 12:02 -0800
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:58 +0000
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 14:30 +0000
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-14 15:35 +0000
      Re: Ruby/Forth challenge for WJ franck.bensusan@gmail.com - 2016-02-14 08:50 -0800
        Re: Ruby/Forth challenge for WJ Julian Fondren <julian.fondren@gmail.com> - 2016-02-14 20:09 -0800
          Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-02-15 08:52 -0800
    Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-14 21:31 +0000
  Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-01-14 22:49 +0000
    Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-14 15:31 -0800
      Re: Ruby/Forth challenge for WJ Melzzzzz <mel@zzzzz.com> - 2016-01-15 06:55 +0100
  Re: Ruby/Forth challenge for WJ djc <ciesinger@gmx.net> - 2016-02-11 07:39 -0800

csiph-web