Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #59178 > unrolled thread
| Started by | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| First post | 2017-05-13 07:34 +0000 |
| Last post | 2017-05-17 15:02 +0000 |
| Articles | 20 on this page of 31 — 9 participants |
Back to article view | Back to comp.lang.forth
Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-13 07:34 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-13 11:16 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-13 11:49 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-13 13:38 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) mhx@iae.nl - 2017-05-13 15:08 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-14 00:51 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-14 07:32 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) mhx@iae.nl - 2017-05-14 02:46 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-14 14:57 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) krishna.myneni@ccreweb.org - 2017-05-15 19:11 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-14 08:14 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) Paul Rubin <no.email@nospam.invalid> - 2017-05-13 15:58 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-14 07:01 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) krishna.myneni@ccreweb.org - 2017-05-14 19:04 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-15 06:10 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) krishna.myneni@ccreweb.org - 2017-05-15 01:49 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-15 14:33 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) "HAA" <someone@microsoft.com> - 2017-05-15 13:44 +1000
Re: Forth-94 vs. Forth-2012 FP data (long) Andrew Haley <andrew29@littlepinkcloud.invalid> - 2017-05-15 04:43 -0500
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-15 15:03 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) "HAA" <someone@microsoft.com> - 2017-05-17 00:10 +1000
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-16 09:04 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-17 15:54 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) mhx@iae.nl - 2017-05-17 10:29 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-17 23:53 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) pahihu <pahihu@gmail.com> - 2017-05-19 02:34 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) Joel Rees <joel.rees@gmail.com> - 2017-05-16 22:48 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-17 06:51 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) Joel Rees <joel.rees@gmail.com> - 2017-05-17 09:29 -0700
Re: Forth-94 vs. Forth-2012 FP data (long) stephen@mpeforth.com (Stephen Pelc) - 2017-05-17 11:07 +0000
Re: Forth-94 vs. Forth-2012 FP data (long) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-05-17 15:02 +0000
Page 1 of 2 [1] 2 Next page →
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-13 07:34 +0000 |
| Subject | Forth-94 vs. Forth-2012 FP data (long) |
| Message-ID | <2017May13.093451@mips.complang.tuwien.ac.at> |
In the last few days I and others have made some claims about the
performance effects of a separate FP stack vs. a combined stack, and
also on the Forth-94 vs. the Forth-2012 standard, i.e, the benefit (to
programmers) of being guaranteed a separate FP stack (Forth-2012)
vs. having to write code that works for a separate FP stack as well as
with a combined stack with any number of cells per FP item (Forth-94).
I decided to try to check these claims empirically. To that end I
wrote a Forth-94 version of FAXPY-NOSTRIDE based on Joel Rees' code,
wrote a matrix multiplication routine, and benchmarked multiplying 2
500x500 matrices (once per benchmark run). Results are from a 4GHz
Core i7-6600K.
Here's the code for the Forth-94 and Forth-2012 versions of
FAXPY-NOSTRIDE:
\ Forth-94
:noname depth >r 0 s>f depth r> - >r fdrop r> ; execute
constant FPCELLWIDTH
fvariable faxpy-ra \ should be a user variable
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
>r 2>r faxpy-ra f! 2r> r>
0 ?DO ( f_x1 f_y1 )
over f@ faxpy-ra f@ f*
FPCELLWIDTH pick f@ f+
FPCELLWIDTH pick f!
float+ swap float+ swap
LOOP
2drop ;
\ Forth-2012
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
0 ?do
fdup over f@ f* dup f@ f+ dup f!
float+ swap float+ swap
loop
2drop fdrop ;
The benchmark executes faxpy-nostride 250k times, and the inner loop
125M times. Here's the inner loop of these two words on VFX with
Ndp387.fth, as well as the inner loop of Gforth's FAXPY primitive
(based on straighforward C code; I guess calling the BLAS routine
daxpy would produce better performance; I show this version to show
what a compiler can do and to get a feeling for how close to the limit
the Forth results are):
VFX Forth-2012 VFX Forth-94 gcc (faxpy)
FLD ST MOV EDX, [EBP] movsd (%rdi),%xmm1
MOV EDX, [EBP] FLD TBYTE 0 [EDX] add %rsi,%rdi
FLD TBYTE 0 [EDX] FLD TBYTE [080A3460] mulsd %xmm0,%xmm1
FMULP ST(1), ST FMULP ST(1), ST addsd (%rdx),%xmm1
FLD TBYTE 0 [EBX] FLD TBYTE 0 [EBX] movsd %xmm1,(%rdx)
FADDP ST(1), ST FADDP ST(1), ST add %rcx,%rdx
FSTP TBYTE 0 [EBX] FSTP TBYTE 0 [EBX] sub $0x1,%r8
ADD EBX, 0A ADD EBX, 0A jne 0x4180b8 <faxpy+8>
MOV EDX, [EBP] MOV EDX, [EBP]
ADD EDX, 0A ADD EDX, 0A
ADD [ESP], 01 ADD [ESP], 01
ADD [ESP+04], 01 ADD [ESP+04], 01
MOV [EBP], EDX MOV [EBP], EDX
JNO 080C6D78 JNO 080C6DB8
So VFX works nicely for optimizing the PICKs, DUPs etc. away here, and
even the variable access does not cause an extra instruction. One
weakness of the VFX code is that the loop control works through
memory, so each iteration takes at least 5 or 6 cycles; the whole FP
part of each iteration looks independent of the other operations, so
the out-of-order execution engine of this CPU should be able to
exploit a lot of parallelism, if we solve the loop control problem.
So I also wrote an unrolled (factor 4) version of the loop, which
should solve the problem. The results are:
gforth VFX/2012 VFX/2012
C faxpy no unrolling unrolled
1155M 1818M 1259M instructions
316M 1432M 1036M cycles
So unrolling buys some speedup and I will show the unrolled results in
the rest of this posting for simplicity of exposition. But despite
this speedup, the result is still more than tree times slower than the
C code, even though the number of instructions is similar. I.e.,
there is still something holding back the out-of-order CPU when
running the VFX code.
One theory I pursued is that the memory accesses for the 10-byte
floats of VFX are at fault, i.e., that there is a false memory
dependency from the fstp of one iteration to the third fld of the next
in many cases, because they access the same word; I successfully
falsified this theory by redefining FLOATS and FLOAT+ for 16-byte
units, and observing that the results did not change. So there must
be some other reason for the performance difference.
Another theory I pursued is that the 387 instructions are no longer
supported well, and that the slowdown is due to this. I checked this
by compiling gforth with "gcc -mfpmath=387". Here are the results:
gforth gforth VFX/2012
C faxpy C faxpy unrolled
SSE 387 387
1155M 1157M 1259M instructions
316M 561M 1036M cycles
So, while 387 instructions cause some slowdown (from
2.5cycles/iteration to 4.5), there are still almost 4 cycles per
iteration unexplained in the VFX results. In the rest of this posting
the gforth results are with SSE instructions (otherwise gcc does not
keep the FTOS in a register).
Anyway, back to the question of Forth-94 vs. Forth-2012 code:
cycles
2012 94
1036M 1163M vfxlin Ndp387.fth
2222M 2949M gforth-fast
12434M 10193M SwiftForth
On VFX the Forth-94 variant is slower by 1 cycle/iteration, on
gforth-fast (which does not optimize stack manipulation much) by 5.8
cycles. On SwiftForth the Forth-94 variant is faster (by 18
cycles/iteration, and it also executes 3.5 instructions/iteration
less), but even the Forth-94 variant is so slow on SwiftForth (81.5
cycles/iteration) that you won't use SwiftForth for this kind of thing
if performance matters.
Looking at the SwiftForth code, the loop body of the Forth-94 variant
is longer by 4 instructions; the code performs a call for every FP
word, and the code for FDUP executes 6 instructions more than that for
F@, explaining 2 of the 3.5 instructions/iteration difference. The
implementations of the floating-point words are not written for time
(or space) efficiency: The FTOS is not cached on the FP stack, and
there is a WAIT instruction (2 cycles on Skylake) at the end of every
FP word. Indeed, FDUP looks as if it was written to perform
pessimally: It loads an FP value from memory to the FPU stack, DUPs it
there, then uses a loop to store these two FP values to memory (i.e.,
including storing to the position where it had just fetched from).
Back to topic: these are all systems/packages that use a separate FP
stack. How well does a combined stack perform? VFX provides 5
different FP packages, three with a separate FP stack, two with a
combined stack.
x86/Ndp387.fth uses the 387 stack as FP stack.
x86/Hfp387.fth uses a stack in memory as FP stack, FTOS on 387 stack
x86/HfpGL32.fth uses a combined stack (32-bit floats)
SoftFP32.separate.fth implements FP using integer arithmetic, separate
SoftFP32.combined.fth implements FP using integer arithmetic, combined
Let's see how they perform:
2012 94
2222M 2949M gforth-fast (for reference)
1036M 1163M vfxlin Ndp387.fth
5156M 7402M vfxlin Hfp387.fth
2596M vfxlin HfpGL32.fth
18967M 19140M vfxlin SoftFP32.separate.fth
10307M vfxlin SoftFP32.combined.fth
Ndp387 performs best by far, but that approach is limited to the 387
(and, less importantly, to 8 FP stack items).
Hfp387 benefits a lot from the Forth-2012 variant, but is surprisingly
slow in either case (41 and 59 instructions/iteration). The source
code looks reasonable (FTOS cached in the FPU, no obvious
inefficiencies), so the slowdown is surprising, especially compared to
gforth-fast, which uses similar techniques.
It storess the F-Stack pointer in a user variable and updates it
there, once for each of the 6 FP operations in the loop, which leads
to dependences through memory, and unlike the loads and stores from f@
and f! in this loop, these are loop-carried dependencies, and thus
their latency determines the performance of this loop; for 6 cycles
latency per update through memory, one iteration takes at least 36
cycles (pretty close to the measures 41 cycles). I have no
explanation for the additional 18 cycles of the Forth-94 variant,
though. By contrast, gforth-fast stores the FP stack pointer in a
register.
The moral: Keeping the FP stack pointer in memory is not necessarily
bad, but don't update it once per FP operation; instead, be a little
more analytical, and update it at the end of the basic block. Or keep
the FP stack pointer in a register, like gforth.
HfpGL32 surprises with its performance, especially once I looked at
the source and object code for F+, which does not look like it is
written for efficiency (it takes 15 instructions compared to 6 for
Hfp387). Looking at the code generated for the inner loop, it becomes
obvious what happens here: having the FP items on the data stack
brought F@ and F! into the realm of VFX's analytical compiler, and we
get pretty good code for everything in the loop except F+ and F*;
that's apparently good enough to get this relatively good result.
But note that HfpGL32 still is slower than gforth-fast with Forth-2012
code, even though gforth-fast has no analytical compiler. My
expectation is that on a variant of VFX with an analytical compiler
that encompasses the FP stack, Hfp387 would outperform HfpGL32 by a
good margin, even if the FP stack pointer is kept in memory between
basic blocks.
The SoftFP32 variants are, unsurprisingly, slow, but it's interesting
that they are not that far off, given that they are written in Forth.
SoftFP32.separate is 71 cycles slower on the Forth-94 variant than
SoftFP32.combined.
My expectation was that the speed difference is small relative to the
overhead of the software FP. But we already saw for the hardware FP
variants that the analytical compiler of VFX does nicely for the
combined stack, so much of these 10M cycles is probably spent in the
software implementations of F* and F+, with the rest of the loop
condensed nicely by the analytical compiler.
By contrast, SoftFP32.separate contains a lot of >FS and FS>, each
time updating the FP stack pointer in memory; and it's not written for
performance: F+ starts with FS> FS> 2SWAP, i.e., two dependent updates
of the FP stack pointer, and ends with >FS. At least that could be
handled better without too much effort.
Conclusion: If we want good performance beyond using the 387 stack as
FP stack, we need an analytical compiler; in that case, keeping the FP
stack pointer in memory is probably good enough. If we don't want to
go there, keeping the FP stack pointer in a register is essential. If
you don't have a compiler that optimizes PICK (e.g., gforth-fast),
Forth-2012 provides a significant performance benefit (in addition to
the programming convenience benefit) over Forth-94; even for VFX with
Ndp387, there is a small benefit for the Forth-2012 variant.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-13 11:16 -0700 |
| Message-ID | <5ac7cdaa-eb0d-4aff-bf3d-08cae53db717@googlegroups.com> |
| In reply to | #59178 |
2017. május 13., szombat 17:29:04 UTC+2 időpontban Anton Ertl a következőt írta: > but even the Forth-94 variant is so slow on SwiftForth (81.5 > cycles/iteration) that you won't use SwiftForth for this kind of thing > if performance matters. Well, if performance matters you have to configure the FP math package in SwiftForth. In the Linux/macOS documentation the section 10.2.1 "Configuring the Floating-Point Options" is TBD though. See the <SwiftForthDir>/lib/options/<platform>/fpconfig.f file. 14395 ms SF3 SW stack, WAIT 4287 ms SF3 HW stack 2602 ms SF3 HW stack, inline 2232 ms gforth-fast 0.7.9 20170406 985 ms iForth5 gforth-fast used to be a little faster/slower on FP code compared to SwiftForth. Regards, pahihu
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-13 11:49 -0700 |
| Message-ID | <aebeabe6-755e-4ba1-8c54-85b6cee895d0@googlegroups.com> |
| In reply to | #59185 |
2017. május 13., szombat 20:16:35 UTC+2 időpontban pahihu a következőt írta: > 14395 ms SF3 SW stack, WAIT > 4287 ms SF3 HW stack > 2602 ms SF3 HW stack, inline > 2232 ms gforth-fast 0.7.9 20170406 > 985 ms iForth5 > > gforth-fast used to be a little faster/slower on FP code compared to SwiftForth. To be fair, the above statement is for the 64bit gforth and the 32bit SwiftForth, iForth5 is 64bit as well. I compiled a 32bit version of gforth-fast, the run time went up to 3841 ms. pahihu
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-13 13:38 -0700 |
| Message-ID | <9b70f694-9b4b-4ebb-9dd2-fc21b8d2001f@googlegroups.com> |
| In reply to | #59187 |
2017. május 13., szombat 20:49:22 UTC+2 időpontban pahihu a következőt írta: > iForth5 is 64bit as well. ... and uses extended precision FP numbers (16 bytes). iForth5 with 8 byte FP numbers gets 580 ms, hand written C code is 350 ms. Not so bad for iForth5. pahihu
[toc] | [prev] | [next] | [standalone]
| From | mhx@iae.nl |
|---|---|
| Date | 2017-05-13 15:08 -0700 |
| Message-ID | <81a0464d-4d3b-44a7-a4d4-44f636cec35a@googlegroups.com> |
| In reply to | #59189 |
On Saturday, May 13, 2017 at 10:38:15 PM UTC+2, pahihu wrote: > 2017. május 13., szombat 20:49:22 UTC+2 időpontban pahihu a következőt írta: > > iForth5 is 64bit as well. > > ... and uses extended precision FP numbers (16 bytes). > iForth5 with 8 byte FP numbers gets 580 ms, hand written C code is 350 ms. > Not so bad for iForth5. > > pahihu If you either like this stuff, or *really* need to multiply matrices, try /dfwforth//examples/benchmar/mmul/mm.frt CLK 3000 MHz 500x500 mm - normal algorithm 1481.22 MFlops, 2.02 ticks/flop, 0.168 s 500x500 mm - blocking, factor of 20 663.94 MFlops, 4.51 ticks/flop, 0.376 s 500x500 mm - transposed B matrix 5973.00 MFlops, 0.50 ticks/flop, 41.855 ms 500x500 mm - transposed B matrix #2 5978.14 MFlops, 0.50 ticks/flop, 41.819 ms 500x500 mm - Robert's algorithm 6089.83 MFlops, 0.49 ticks/flop, 41.052 ms 500x500 mm - T. Maeno's algorithm, subarray 20x20 879.28 MFlops, 3.41 ticks/flop, 0.284 s 500x500 mm - D. Warner's algorithm, subarray 20x20 832.92 MFlops, 3.60 ticks/flop, 0.300 s 500x500 mm - generic mat* 25347.25 MFlops, 0.11 ticks/flop, 9.863 ms 500x500 mm - iForth DGEMM1 30193.23 MFlops, 0.09 ticks/flop, 8.280 ms 500x500 mm - iForth SMMD* 31375.50 MFlops, 0.09 ticks/flop, 7.968 ms 500x500 mm - iForth DAXPY based 5976.42 MFlops, 0.50 ticks/flop, 41.831 ms This is a mix of FPU and SSE. -marcel
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-14 00:51 -0700 |
| Message-ID | <13954b38-21e5-47f2-ac06-8437cae50d16@googlegroups.com> |
| In reply to | #59191 |
2017. május 14., vasárnap 0:08:21 UTC+2 időpontban m...@iae.nl a következőt írta: > If you either like this stuff, or *really* need to multiply > matrices, try /dfwforth//examples/benchmar/mmul/mm.frt > I had to get libgoto_core2-r1.26.dylib from dfwforth v4 and it worked. I used to use for C code http://www.netlib.org/atlas pahihu
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-14 07:32 +0000 |
| Message-ID | <2017May14.093205@mips.complang.tuwien.ac.at> |
| In reply to | #59191 |
mhx@iae.nl writes:
>If you either like this stuff, or *really* need to multiply
>matrices, try /dfwforth//examples/benchmar/mmul/mm.frt
But it suffers from non-portability. It does not load on gforth,
SwiftForth, or VFX.
VFX includes a variant of this file that does not load without ado on
gforth, SwiftForth, or even vfxlin (it uses "\" as directory
separator). It contains harnesses for various Forth systems, but
requires changing the source file in order to change the harness.
Sigh.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | mhx@iae.nl |
|---|---|
| Date | 2017-05-14 02:46 -0700 |
| Message-ID | <a1903286-62f9-4276-afd8-958d215ca19b@googlegroups.com> |
| In reply to | #59214 |
On Sunday, May 14, 2017 at 10:00:47 AM UTC+2, Anton Ertl wrote: > mhx@iae.nl writes: > >If you either like this stuff, or *really* need to multiply > >matrices, try /dfwforth//examples/benchmar/mmul/mm.frt > > But it suffers from non-portability. It does not load on gforth, > SwiftForth, or VFX. > > VFX includes a variant of this file that does not load without ado on > gforth, SwiftForth, or even vfxlin (it uses "\" as directory > separator). It contains harnesses for various Forth systems, but > requires changing the source file in order to change the harness. > > Sigh. > > - anton > -- > M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html > comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html > New standard: http://www.forth200x.org/forth200x.html > EuroForth 2017: http://www.euroforth.org/ef17/ I posted mmu.frt on CLF long ago(https://groups.google.com/d/msg/comp.lang.forth/HljHYyMLob0/Zb7ay74dnWkJ , sorry -- no decent reference possible with Google). I think portability is driven by people wanting to run other's code, and *complaining when it doesn't.* When it is too easy to fix the problem, Forth programmers don't bother to signal the vendor about problems. We need more clueless newbies (and listen to them). Some common problems where some standardization (or at least a heated discussion) could help: 1. Installing, enabling and disabling features (like FP and doubles, setting up editor, help system, graphics), terminal, keyboard, and mouse definitions 2. system-independent specification of paths, files, directories (esp. how to work with relative includes) 3. Foreign function interface (call C, Fortran, system, callbacks) 4. Generating executables and dll/so's 5. Centralized repository of common/uncommon words (not 'only' libraries) 6. Parallel execution, threads, tasks 7. graphics standard (at least for simple plots) 8. An (informal) testing standard, how to present published code. Maybe FORML should come back. -marcel
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-14 14:57 +0000 |
| Message-ID | <2017May14.165752@mips.complang.tuwien.ac.at> |
| In reply to | #59216 |
mhx@iae.nl writes:
>I posted mmu.frt on CLF long ago(https://groups.google.com/d/msg/comp.lang.forth/HljHYyMLob0/Zb7ay74dnWkJ ,
>sorry -- no decent reference possible with Google).
There are two mmu.frt in the current iforth distribution:
dfwforth/examples/benchmar/mmu.frt contains the benchmarks from
<http://www.complang.tuwien.ac.at/forth/bench.zip> in one file, preceded by
non-portable timing code.
dfwforth/examples/benchmar/mmul/mmu.frt contains the matrix multiply
stuff, but you need to modify the file in order to run it on a
different system. But even before checking for the system, it starts
with the non-standard word ANEW (which means it does not load on
Gforth and SwiftForth). vfxlin takes that hurdle, but then trips over
S" ../../lib/ndp387.fth" INCLUDED
When I comment out the ANEW, gforth trips over
include fsl_utilgf.fs
and the next line
INCLUDE dynmem.fs
also looks suspicious. I have no such files anywhere (Gforth comes
with a file fsl-util.4th, however, but I have no idea what dynmem.fs
refers to), neither in the dfwforth files, nor in the Gforth files.
>I think portability is driven by people wanting to run
>other's code, and *complaining when it doesn't.*
There are two sides to the issue. The recipient of the complaint
needs to then actually fix the portability problem, and give feedback
that it has been fixed.
As a program author, you can also be a little bit proactive, and try
the program out on a number of systems. And when you do that
regularly, you want to do it with scripts, such as
for FORTH in "gforth -e" sf vfxlin iforth; do
$FORTH "include program.4th run-test bye"
done
And then it becomes pretty obvious that changing the source file to
configure the Forth system is not a winner (there are other reasons,
too). Conversely, if you make it inconvenient to test your program on
different systems, you won't be testing it on different systems, and
then your program will not be portable.
> When
>it is too easy to fix the problem, Forth programmers
>don't bother to signal the vendor about problems.
My experience is: When the vendor prefers to make excuses why the
problem is not a real problem, I stop reporting such problems to him.
>2. system-independent specification of paths, files, directories
>(esp. how to work with relative includes)
When I pursued this, there were a few programmers who were interested
in it, one vendor who was dead set against it, and otherwise, very
little support either way. I eventually gave up after failing to
achieve consensus on even the most basic things.
A new effort was started at the last meeting, and I wish them well.
If you want to see something come out of it, then don't just lean back
when they produce something, in the assumption that it will eventually
come through. Express your support (and, if necessary, criticism).
>3. Foreign function interface (call C, Fortran, system, callbacks)
That's on my ToDo list, although maybe less ambitious than this list.
>6. Parallel execution, threads, tasks
That's also on the Forth200x ToDo list (I think Bernd Paysan is one of
those who is tasked to work on this).
>8. An (informal) testing standard, how to present published code.
For testing we have the enhanced Hayes tester ttester.fs.
For presenting published code, theforth.net has guidelines:
<http://theforth.net/guidelines>
Of course, one may want additional properties for the packages (such
as "options should be settable without changing the source code"), but
I think the basic guidelines are long enough, and the rest should be
part of a common consensus that someone may write down as a memo or
checklist.
>Maybe FORML should come back.
There is EuroForth, this year near Vienna. Maybe you can take the
time to participate.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | krishna.myneni@ccreweb.org |
|---|---|
| Date | 2017-05-15 19:11 -0700 |
| Message-ID | <dac7ce84-3183-45c4-8ae9-787a57f6e0c6@googlegroups.com> |
| In reply to | #59221 |
On Sunday, May 14, 2017 at 11:07:50 AM UTC-5, Anton Ertl wrote: > mhx@iae.nl writes: > >I posted mmu.frt on CLF long ago(https://groups.google.com/d/msg/comp.lang.forth/HljHYyMLob0/Zb7ay74dnWkJ , ... > > include fsl_utilgf.fs > This is the original file which is equivalent to fsl-util.fs in the gforth distribution. The latter is my name for the FSL utility file, and I may have added some corrections or enhancements. It should work the same. > and the next line > > INCLUDE dynmem.fs > > also looks suspicious. I have no such files anywhere (Gforth comes > with a file fsl-util.4th, however, but I have no idea what dynmem.fs > refers to) ... The file dynmem.fs is part of the FSL. See, for example, ftp://ccreweb.org/software/gforth/fsl/dynmem.fs > > >I think portability is driven by people wanting to run > >other's code, and *complaining when it doesn't.* > > There are two sides to the issue. Marcel's code is often portable to strict ANS Forth systems which have some facility extensions. I ported mmu.frt to kforth shortly after he posted it on c.l.f. It probably took me an hour or two. Krishna
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-14 08:14 +0000 |
| Message-ID | <2017May14.101423@mips.complang.tuwien.ac.at> |
| In reply to | #59185 |
pahihu <pahihu@gmail.com> writes:
>Well, if performance matters you have to configure the FP math package in S=
>wiftForth.
>In the Linux/macOS documentation the section 10.2.1 "Configuring the Floati=
>ng-Point Options"
>is TBD though. See the <SwiftForthDir>/lib/options/<platform>/fpconfig.f fi=
>le.
Cool that you have this much flexibility in configuring it. It's not
so great that you have to change the SwiftForth source files to
achieve that.
Using the hardware stack and no WAIT gives a pretty good-looking F+:
just an fadd instruction; remaining inefficiencies: FP words are not
inlined, and F@ and F! jump to DF@ DF!, which do the actual work. The
result is:
cycles
2012 94
1036M 1163M vfxlin Ndp387.fth
2222M 2949M gforth-fast
4860M 5086M SwiftForth HW stack, no WAIT
12434M 10193M SwiftForth SW stack, WAIT
Hmm, normally well-predicted calls, jumps and returns are pretty fast
(1 cycle) on these CPUs; that would explain 2050M cycles, but where is
the rest coming from? Maybe these CPUs don't like it if the calls and
returns occur too frequently; certainly the 4 cycles per dispatch
result for subroutine threading on the Core i7-4690K
<https://www.complang.tuwien.ac.at/forth/threading/> points in that
direction.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2017-05-13 15:58 -0700 |
| Message-ID | <871srsbbz6.fsf@nightsong.com> |
| In reply to | #59178 |
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes: > by compiling gforth with "gcc -mfpmath=387". Could you try with -ffast-math ?
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-14 07:01 +0000 |
| Message-ID | <2017May14.090137@mips.complang.tuwien.ac.at> |
| In reply to | #59194 |
Paul Rubin <no.email@nospam.invalid> writes:
>anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>> by compiling gforth with "gcc -mfpmath=387".
>
>Could you try with -ffast-math ?
Same result, and the loop looks the same. If you are thinking about
auto-vectorization, I don't expect it: The stride arguments of FAXPY
pretty much prevent it. Also, I think that gcc-4.9 is not very good
at it.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | krishna.myneni@ccreweb.org |
|---|---|
| Date | 2017-05-14 19:04 -0700 |
| Message-ID | <2043fde8-1ab2-463d-b873-e62ed82446f1@googlegroups.com> |
| In reply to | #59178 |
On Saturday, May 13, 2017 at 10:29:04 AM UTC-5, Anton Ertl wrote: > In the last few days I and others have made some claims about the > performance effects of a separate FP stack vs. a combined stack, and > also on the Forth-94 vs. the Forth-2012 standard, i.e, the benefit (to > programmers) of being guaranteed a separate FP stack (Forth-2012) > vs. having to write code that works for a separate FP stack as well as > with a combined stack with any number of cells per FP item (Forth-94). > > I decided to try to check these claims empirically. ... > Let's see how they perform: > > 2012 94 > 2222M 2949M gforth-fast (for reference) > 1036M 1163M vfxlin Ndp387.fth > 5156M 7402M vfxlin Hfp387.fth > 2596M vfxlin HfpGL32.fth > 18967M 19140M vfxlin SoftFP32.separate.fth > 10307M vfxlin SoftFP32.combined.fth > ... > Conclusion: If we want good performance beyond using the 387 stack as > FP stack, we need an analytical compiler; ... > Forth-2012 provides a significant performance benefit (in addition to > the programming convenience benefit) over Forth-94; even for VFX with > Ndp387, there is a small benefit for the Forth-2012 variant. > ... I don't think these comparisons are particularly useful. Normally, I'm wary of discussing Forth philosophy as such discussions don't lead to useful results. However, this particular case seems particularly relevant to such a discussion. When a higher level abstraction is necessary, Forth can be used to build a DSL to support the abstraction (e.g. a framework for modular programming, or for object-oriented programming). However, for the case of highly efficient floating point matrix multiplication, the most appropriate coding, which is also not particularly hard for this case, is assembly language. Forth supports writing and calling words in assembler. It's not that I'm opposed to optimizing compilers, but use of the right tools provided you will make the differences between systems (VFX, SwiftForth, gforth) and the standards (Forth-94 vs Forth-2012) disappear to the level of a percent or two. Krishna
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-15 06:10 +0000 |
| Message-ID | <2017May15.081027@mips.complang.tuwien.ac.at> |
| In reply to | #59236 |
krishna.myneni@ccreweb.org writes:
>However, for the case of hi=
>ghly efficient floating point matrix multiplication, the most appropriate c=
>oding, which is also not particularly hard for this case, is assembly langu=
>age. Forth supports writing and calling words in assembler.
No, for high-performance matrix multiplication, the most appropriate
thing is to call a library routine, despite the anti-library stance
frequently espoused here (e.g., '"standard libraries" full of
inefficient code to take care of all possible cases, etc.'
<yPGdnRKY5J87K4vEnZ2dnUU7-aPNnZ2d@supernews.com>). The people who
wrote the matrix multiplication libraries have put months of work
based on years of work by others into making these libraries fast.
It's unlikely that you or I will do better without putting as much
work in. Also, because these libraries are written for common
interfaces, it's easier to make code using them portable. E.g., your
assembly code for SwiftForth will not work on iForth and vice versa,
because these two systems are written for different instruction sets
(despite running on the same machines).
But the purpose of this test was not to get the fastest matrix
multiplication possible, but to check the claims that I and others
have made about the performance of Forth-94 FP code vs. Forth-2012 FP
code, and about the performance of a separate vs. a combined stack.
And you cannot check that by writing the matrix multiplication in
assembly, or calling a library routine.
We had the same routine FAXPY-NOSTRIDE available in close-to-Forth-94
(written by someone who advocates this way of writing FP code) and in
Forth-2012 (written by someone who advocates this way of writing FP
code), so I used that for this comparison. You can write matrix
multiplication with FAXPY-NOSTRIDE, so I used that for the benchmark.
If you want to use Forth FP only in those cases where performance does
not matter, then all the performance claims that have been made here
and the performance results that I found become irrelevant. It would
be good enough to keep the FP stack pointer in a user variable, and
update it on every FP operation (which turned out to be expensive in
my results). In that case we can focus on what's easier to write; and
there Forth-2012 wins.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | krishna.myneni@ccreweb.org |
|---|---|
| Date | 2017-05-15 01:49 -0700 |
| Message-ID | <a4233da0-6cff-47e5-9239-344a50bf201e@googlegroups.com> |
| In reply to | #59263 |
On Monday, May 15, 2017 at 1:41:40 AM UTC-5, Anton Ertl wrote: > krishna.....org writes: > >However, for the case of hi= > >ghly efficient floating point matrix multiplication, the most appropriate c= > >oding, which is also not particularly hard for this case, is assembly langu= > >age. Forth supports writing and calling words in assembler. > > No, for high-performance matrix multiplication, the most appropriate > thing is to call a library routine, despite the anti-library stance > frequently espoused here (e.g., '"standard libraries" full of > inefficient code to take care of all possible cases, etc.' > <yPGdnRKY5J87K4vEnZ2dnUU7-aPNnZ2d@supernews.com>). The people who > wrote the matrix multiplication libraries have put months of work > based on years of work by others into making these libraries fast. > It's unlikely that you or I will do better without putting as much > work in. ... I'm going to restrict my statement to the example you gave here. A word like FAXPY is trivial to code in assembler, with the 387 instructions. If you're talking about non-trivial numerical computation library routines which took months to develop, it is unlikely that they were originally written as Forth source code, but rather in Fortran or C, and would indeed take months of effort to translate and test into Forth source. I have done several such translations myself of Fortran source code found on netlib, e.g. ftp://ccreweb.org/software/kforth/examples/fsl/extras/zwofz.4th ftp://ccreweb.org/software/kforth/examples/fsl/extras/jairy.4th ftp://ccreweb.org/software/kforth/examples/fsl/extras/bes-jy.4th Indeed, it took much effort and test code (note the test code at the end of the files) to ensure I had a faithful translation. Some Forth purists, here on c.l.f., were aghast at the idea of translating Fortan code to Forth, rather than starting from scratch to encode the algorithms in Forth -- a position I don't consider to be very practical. Alex Wegel and I began some work to port the multi-dimensional integration package, cubature, to Forth -- a package I wanted to use. But I'm afraid that project dropped when I couldn't commit enough time to it. So, unless the Forth community has enough interest to devote to a massive effort to translate important numerical algorithms into Forth, the practical answer for such cases is to call the functions from pre-compiled libraries. It's not my first choice, but the time required to translate or rewrite from scratch is often not practical. > Also, because these libraries are written for common > interfaces, it's easier to make code using them portable. E.g., your > assembly code for SwiftForth will not work on iForth and vice versa, > because these two systems are written for different instruction sets > (despite running on the same machines). > Yes, portability will be a problem, except for those cases where the assembly code is essentially trivial, as in the case for FAXPY. > But the purpose of this test was not to get the fastest matrix > multiplication possible, but to check the claims that I and others > have made about the performance of Forth-94 FP code vs. Forth-2012 FP > code, and about the performance of a separate vs. a combined stack. > And you cannot check that by writing the matrix multiplication in > assembly, or calling a library routine. > > We had the same routine FAXPY-NOSTRIDE available in close-to-Forth-94 > (written by someone who advocates this way of writing FP code) and in > Forth-2012 (written by someone who advocates this way of writing FP > code), so I used that for this comparison. You can write matrix > multiplication with FAXPY-NOSTRIDE, so I used that for the benchmark. > > If you want to use Forth FP only in those cases where performance does > not matter, then all the performance claims that have been made here > and the performance results that I found become irrelevant. It would > be good enough to keep the FP stack pointer in a user variable, and > update it on every FP operation (which turned out to be expensive in > my results). In that case we can focus on what's easier to write; and > there Forth-2012 wins. > For this particular case, and for the particular way in which it was coded, one can draw that conclusion. But I'm not against high-performance algorithms written in Forth. I'm suggesting that one should consider the relevant tool for a particular problem, whether it's coding in assembler, calling a library routine, or translating to Forth a non-trivial algorithm. Marcel's mmu.frt provides some different matrix multiplication algorithms. The best way to use them in a Forth environment may indeed be as Forth source loaded by an optimizing compiler. Krishna
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-15 14:33 +0000 |
| Message-ID | <2017May15.163301@mips.complang.tuwien.ac.at> |
| In reply to | #59269 |
krishna.myneni@ccreweb.org writes:
>On Monday, May 15, 2017 at 1:41:40 AM UTC-5, Anton Ertl wrote:
>> krishna.....org writes:
>> >However, for the case of hi=3D
>> >ghly efficient floating point matrix multiplication, the most appropriat=
>e c=3D
>> >oding, which is also not particularly hard for this case, is assembly la=
>ngu=3D
>> >age. Forth supports writing and calling words in assembler.
>>=20
>> No, for high-performance matrix multiplication, the most appropriate
>> thing is to call a library routine, despite the anti-library stance
>> frequently espoused here (e.g., '"standard libraries" full of
>> inefficient code to take care of all possible cases, etc.'
>> <yPGdnRKY5J87K4vEnZ2dnUU7-aPNnZ2d@supernews.com>). The people who
>> wrote the matrix multiplication libraries have put months of work
>> based on years of work by others into making these libraries fast.
>> It's unlikely that you or I will do better without putting as much
>> work in. ...
>
>I'm going to restrict my statement to the example you gave here. A word lik=
>e FAXPY is trivial to code in assembler, with the 387 instructions.
That may be the case, but that does not mean that it is the
appropriate thing for "highly efficient floating point matrix
multiplication".
And especially for the 387, the code coming from VFX+Ndp387 is just
the same as what one would write in assembly language. It admittedly
has the loop control problem, but that should not be too hard to solve
if MPE puts their minds to it; I am mystified by the performance
problem of the unrolled version, but then there is no way to tell that
that would not happen with hand-written assembly language.
> If you'=
>re talking about non-trivial numerical computation library routines which t=
>ook months to develop, it is unlikely that they were originally written as =
>Forth source code, but rather in Fortran or C, and would indeed take months=
> of effort to translate and test into Forth source. I have done several suc=
>h translations myself of Fortran source code found on netlib, e.g.
>
>ftp://ccreweb.org/software/kforth/examples/fsl/extras/zwofz.4th
>ftp://ccreweb.org/software/kforth/examples/fsl/extras/jairy.4th
>ftp://ccreweb.org/software/kforth/examples/fsl/extras/bes-jy.4th
No, I am not referring to non-trivial computations, I am referring to
a trivial computation like matrix multiplication. You can code it in
a few lines of Forth, C, or Fortran code, or a few more lines of
assembly language code, but the performance will suck, because it does
not take machine characteristics into account (not even the assembly
version). Because matrix multiplication performance is an important
selling argument (e.g., the supercomputer top 500 is based on matrix
multiplication performance), computer and CPU manufacturers have
people who spend months optimizing it to get the most out of each
specific machine; R. Clint Whaley has been working on ATLAS
(admittedly, not just matrix multiplication, but other linear algebra
software as well) for 20 years, and he is not the only one working on
ATLAS.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2017-05-15 13:44 +1000 |
| Message-ID | <ofb87j$7hq$1@gioia.aioe.org> |
| In reply to | #59178 |
Anton Ertl wrote: > In the last few days I and others have made some claims about the > performance effects of a separate FP stack vs. a combined stack, and > also on the Forth-94 vs. the Forth-2012 standard, i.e, the benefit (to > programmers) of being guaranteed a separate FP stack (Forth-2012) > vs. having to write code that works for a separate FP stack as well as > with a combined stack with any number of cells per FP item (Forth-94). > > I decided to try to check these claims empirically. To that end I > wrote a Forth-94 version of FAXPY-NOSTRIDE based on Joel Rees' code, > wrote a matrix multiplication routine, and benchmarked multiplying 2 > 500x500 matrices (once per benchmark run). Results are from a 4GHz > Core i7-6600K. > ... How about this for an 'empirical' check. Write a real-world application for which hardware f/p is not available. Implement it using combined and separate stack f/p. Compare the performance and memory used. Expect to see much difference? Neither do I. 200x did not - nor can it - demonstrate a technical reason for requiring *implementers* provide a separate f/p stack. That's because the existence of combined stack systems affected nobody but themselves. All 200x did was take choice away from the implementer - something ANS went to lengths to avoid. Forth should not be about imposing ideology. Forth-83 tried it with floored division. All it succeeded in doing was to make itself look foolish. 200x the same.
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2017-05-15 04:43 -0500 |
| Message-ID | <McudnWzgute15YTEnZ2dnUU7-K-dnZ2d@supernews.com> |
| In reply to | #59240 |
HAA <someone@microsoft.com> wrote: > > 200x did not - nor can it - demonstrate a technical reason for requiring > *implementers* provide a separate f/p stack. You are writing in a very odd way. Anton describes at some length the technical reasons for requiring a separate FP stack, and you then say that 200x did not demonstrate a technical reason. Andrew.
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-15 15:03 +0000 |
| Message-ID | <2017May15.170302@mips.complang.tuwien.ac.at> |
| In reply to | #59240 |
"HAA" <someone@microsoft.com> writes:
>How about this for an 'empirical' check. Write a real-world application
>for which hardware f/p is not available. Implement it using combined
>and separate stack f/p. Compare the performance and memory used.
>Expect to see much difference? Neither do I.
I didn't expect it for the matrix multiplication case, but I actually
measured it and found a difference, and found an explanation for the
difference. Maybe you should actually read the whole posting before
replying.
>200x did not - nor can it - demonstrate a technical reason for requiring
>*implementers* provide a separate f/p stack.
Certainly no technical reason that you will acknowledge.
>That's because the
>existence of combined stack systems affected nobody but themselves.
The issue of whether the programmer has to write code such that it
works on both separate-stack and combined-stack systems affects all
programmers who write FP code. And the programmers of the FSL voted
with their feet and did not write Forth-94 compliant programs, but
programs for separate-stack systems. And popular systems provide
separate-stack implementations. So separate stacks are common
practice. If we did not put common practice in the standard, we would
not be doing our job.
But if you prefer to write Forth-94 compliant code (i.e., it works on
separate-stack systems and all flavours of combined-stack systems),
there's good news for you: You can continue doing that; this code is
also Forth-2012 compliant.
>All 200x did was take choice away from the implementer
Well, tough luck for the implementer. Do we suffer from too few
implementors or from too few programmers?
But did we actually do that? VFX still provides combined-stack
packages in addition to the separate-stack packages, and that's fine.
And even if you are an implementor who only wants to provide a
combined-stack package, the only thing taken away from you is the
possibility to label your system a "Forth-2012 system providing the
floating-point wordset".
>- something
>ANS went to lengths to avoid.
If they avoided taking away choice from the implementor, they would
not have required that OR performs an inclusive-or (and that's in
core, so it is a hard requirement). Actually the only away to avoid
taking any choice away from implementors is to not require anything in
the standard. Then the standard is completely useless, but it avoids
to "take choice away from the implementors".
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2017: http://www.euroforth.org/ef17/
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.forth
csiph-web