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 | 11 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 2 of 2 — ← Prev page 1 [2]
| From | "HAA" <someone@microsoft.com> |
|---|---|
| Date | 2017-05-17 00:10 +1000 |
| Message-ID | <off1fm$f7n$1@gioia.aioe.org> |
| In reply to | #59314 |
Anton Ertl wrote:
> "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.
Performance has never been the sole criteria by which TC's made
decisions, so let's ditch that as a reason for excluding common
stacks systems from 2012.
What's left is the alleged difficulty ANS imposed on f/p programmers.
It's been claimed by you - and now by 2012 (C.7.2) - that ANS required
programmers to either code for a common stack, or to declare a
dependency on a separate stack. There is in fact no such stipulation
in ANS - quite the opposite. Sections or parts thereof in ANS which
dispelled such allegations have been either removed or reworded by
2012, leaving the reader to believe 2012 has given them something
they didn't, or couldn't, have with ANS. Here's what ANS said
(emphasis added):
12.3.3
"BY DEFAULT the floating-point stack SHALL be separate from
the data and return stacks.
A program MAY determine whether floating-point numbers are
kept on the data stack by passing the string "FLOATING-STACK"
to ENVIRONMENT?."
A.12
"Floating-point stack: BY DEFAULT the floating-point stack IS
separate from the data and return stacks; HOWEVER, an
implementation MAY keep floating-point numbers on the data
stack."
ANS left no doubt "separate stack" is the "default" and common stack
was an option for implementers who wanted or needed it. ANS went to
pains to over this e.g. FDEPTH refers to the "default separate floating-
point stack".
Is a separate stack program required to declare a dependency on a
separate stack? Logically it would be redundant since ANS stated
separate stack is the default. In any case no such dependency is listed:
12.4.2 Program documentation
12.4.2.1 Environmental dependencies
- requiring the floating-point stack to be larger than six items
(12.3.3 Floating-point stack).
12.4.2.2 Other program documentation
- no additional requirements.
Had 200x TC found ANS' statements ambiguous (hard to believe had they
actually read ANS), could they have rewritten them without having to remove
common stack systems? I don't see why not. So why were common stack
systems excluded from 2012? I believe the answer can be found here:
"Whilst every sane Forth has a separate floating-point stack,
it is not strictly required; an ANS Forth system could theoretically
keep floating-point numbers on the data stack. As an additional
difficulty, you don't know how many cells a floating-point number
takes. It is reportedly possible to write words in a way that they
work also for a unified stack model, but we do not recommend
trying it."
That statement, which has appeared in gforth's documentation since
at least 1998, presents an opinion. It is clear the author holds a view
that is intolerant of combined stack f/p and of those who implement it.
> If we did not put common practice in the standard, we would
> not be doing our job.
Removing common stack implementations with no technical justification.
Propagating opinion and statements known to be fallacious, or at the
very least, contentious. Including these in a Standard document as fact.
Is this the job of a responsible technical committee which claims to
speak on behalf of Forth users?
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-16 09:04 -0700 |
| Message-ID | <047bed2a-b743-40dc-b978-aa592d3797f9@googlegroups.com> |
| In reply to | #59178 |
> 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.
You can even write a PICK-less variant in ANS-94, which does not depend
on the FP cell width. Testing on SwiftForth, iForth, VFX, gforth I don't
see clear performance advantage of the separate FP stack version either.
pahihu
fvariable faxpy-ra \ should be a user variable
: faxpy-nostride941 ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
>r 2>r faxpy-ra f! 2r> r>
0 ?DO ( f_x1 f_y1 )
>R
dup float+ swap f@
faxpy-ra f@ f*
R@ f@ f+ R@ f!
R> float+
LOOP
2drop ;
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-17 15:54 +0000 |
| Message-ID | <2017May17.175419@mips.complang.tuwien.ac.at> |
| In reply to | #59379 |
pahihu <pahihu@gmail.com> writes:
>You can even write a PICK-less variant in ANS-94, which does not depend
>on the FP cell width. Testing on SwiftForth, iForth, VFX, gforth I don't
>see clear performance advantage of the separate FP stack version either.
>
>pahihu
>
>fvariable faxpy-ra \ should be a user variable
>: faxpy-nostride941 ( ra f_x f_y ucount -- )
> \ vy=ra*vx+vy
> >r 2>r faxpy-ra f! 2r> r>
> 0 ?DO ( f_x1 f_y1 )
> >R
> dup float+ swap f@
> faxpy-ra f@ f*
> R@ f@ f+ R@ f!
> R> float+
> LOOP
> 2drop ;
Looks better than the PICK-heavy variant, but still cumbersome
compared to the Forth-2012 version.
Performance: On a Core i7-4690K (no SwiftForth or iForth installed),
with the unrolled versions:
cycles
Forth-2012 Forth-94 Forth-94
Rees/Ertl pahihu
2929M 3691M 3480M gforth-fast
1289M 1414M 1574M vfxlin Ndp387
Looks like a win for the Forth-2012 code to me.
The inner loop for the non-unrolled variants are on VFX:
Forth-2012 Forth-94 Rees/Ertl Forth-94 pahihu
FLD ST MOV EDX, [EBP] PUSH EBX
MOV EDX, [EBP] FLD TBYTE 0 [EDX] MOV EBX, [EBP]
FLD TBYTE 0 [EDX] FLD TBYTE [080A3460] MOV EDX, EBX
FMULP ST(1), ST FMULP ST(1), ST ADD EBX, 0A
FLD TBYTE 0 [EBX] FLD TBYTE 0 [EBX] FLD TBYTE 0 [EDX]
FADDP ST(1), ST FADDP ST(1), ST FLD TBYTE [080A3460]
FSTP TBYTE 0 [EBX] FSTP TBYTE 0 [EBX] FMULP ST(1), ST
ADD EBX, 0A ADD EBX, 0A MOV EDX, [ESP]
MOV EDX, [EBP] MOV EDX, [EBP] FLD TBYTE 0 [EDX]
ADD EDX, 0A ADD EDX, 0A FADDP ST(1), ST
ADD [ESP], 01 ADD [ESP], 01 MOV EDX, [ESP]
ADD [ESP+04], 01 ADD [ESP+04], 01 FSTP TBYTE 0 [EDX]
MOV [EBP], EDX MOV [EBP], EDX POP EDX
JNO 080C6D78 JNO 080C6DB8 ADD EDX, 0A
ADD [ESP], 01
ADD [ESP+04], 01
MOV [EBP], EBX
MOV EBX, EDX
JNO 080C6A88
VFX does not (yet?) analyse and optimize the return stack; or, if you
feel nasty, you could say: it optimizes PICK better than >R R> and R@.
- 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-17 10:29 -0700 |
| Message-ID | <d86e3505-db26-4e5b-b615-e61cea93c9f6@googlegroups.com> |
| In reply to | #59432 |
On Wednesday, May 17, 2017 at 6:14:04 PM UTC+2, Anton Ertl wrote:
> pahihu <pahihu@gmail.com> writes:
> >You can even write a PICK-less variant in ANS-94, which does not depend
> >on the FP cell width. Testing on SwiftForth, iForth, VFX, gforth I don't
> >see clear performance advantage of the separate FP stack version either.
> >
> >pahihu
> >
> >fvariable faxpy-ra \ should be a user variable
> >: faxpy-nostride941 ( ra f_x f_y ucount -- )
> > \ vy=ra*vx+vy
> > >r 2>r faxpy-ra f! 2r> r>
> > 0 ?DO ( f_x1 f_y1 )
> > >R
> > dup float+ swap f@
> > faxpy-ra f@ f*
> > R@ f@ f+ R@ f!
> > R> float+
> > LOOP
> > 2drop ;
>
> Looks better than the PICK-heavy variant, but still cumbersome
> compared to the Forth-2012 version.
>
> Performance: On a Core i7-4690K (no SwiftForth or iForth installed),
> with the unrolled versions:
>
> cycles
> Forth-2012 Forth-94 Forth-94
> Rees/Ertl pahihu
> 2929M 3691M 3480M gforth-fast
> 1289M 1414M 1574M vfxlin Ndp387
>
> Looks like a win for the Forth-2012 code to me.
>
> The inner loop for the non-unrolled variants are on VFX:
>
> Forth-2012 Forth-94 Rees/Ertl Forth-94 pahihu
> FLD ST MOV EDX, [EBP] PUSH EBX
> MOV EDX, [EBP] FLD TBYTE 0 [EDX] MOV EBX, [EBP]
> FLD TBYTE 0 [EDX] FLD TBYTE [080A3460] MOV EDX, EBX
> FMULP ST(1), ST FMULP ST(1), ST ADD EBX, 0A
> FLD TBYTE 0 [EBX] FLD TBYTE 0 [EBX] FLD TBYTE 0 [EDX]
> FADDP ST(1), ST FADDP ST(1), ST FLD TBYTE [080A3460]
> FSTP TBYTE 0 [EBX] FSTP TBYTE 0 [EBX] FMULP ST(1), ST
> ADD EBX, 0A ADD EBX, 0A MOV EDX, [ESP]
> MOV EDX, [EBP] MOV EDX, [EBP] FLD TBYTE 0 [EDX]
> ADD EDX, 0A ADD EDX, 0A FADDP ST(1), ST
> ADD [ESP], 01 ADD [ESP], 01 MOV EDX, [ESP]
> ADD [ESP+04], 01 ADD [ESP+04], 01 FSTP TBYTE 0 [EDX]
> MOV [EBP], EDX MOV [EBP], EDX POP EDX
> JNO 080C6D78 JNO 080C6DB8 ADD EDX, 0A
> ADD [ESP], 01
> ADD [ESP+04], 01
> MOV [EBP], EBX
> MOV EBX, EDX
> JNO 080C6A88
>
> VFX does not (yet?) analyse and optimize the return stack; or, if you
> feel nasty, you could say: it optimizes PICK better than >R R> and R@.
In iForth the 4 times unrolled variant with visible arguments will be
something like
0e dfvalue faxpy-ra
: faxpy-nostride941 ( ra f_x f_y ucount )
\ vy=ra*vx+vy
>r 2>r TO faxpy-ra 2r> r>
0 ?DO ( f_x1 f_y1 )
>R df@+ faxpy-ra f* R@ df@ f+ R@ df! R> dfloat+
>R df@+ faxpy-ra f* R@ df@ f+ R@ df! R> dfloat+
>R df@+ faxpy-ra f* R@ df@ f+ R@ df! R> dfloat+
>R df@+ faxpy-ra f* R@ df@ f+ R@ df! R> dfloat+
LOOP
2drop ;
create f[] 16 dfloats allot
create g[] 16 dfloats allot
: test 23e f[] g[] 4 faxpy-nostride941 ;
FORTH> ' test idis
$01326C00 : test
$01326C0A fld $012BCAC0 tbyte-offset
$01326C10 fstp $01325D90 qword-offset
$01326C16 push $013266C0 d#
$01326C1B push $01326750 d#
$01326C20 mov rcx, 4 d#
$01326C27 xor rbx, rbx
$01326C2A call (?DO) offset NEAR
$01326C34 lea rax, [rax 0 +] qword
$01326C38 pop rdi
$01326C39 fld [rdi] qword
$01326C3B fld $01325D90 qword-offset
$01326C41 fmulp ST(1), ST
$01326C43 fld [rbx] qword
$01326C45 faddp ST(1), ST
$01326C47 fstp [rbx] qword
$01326C49 fld [rdi 8 +] qword
$01326C4C fld $01325D90 qword-offset
$01326C52 fmulp ST(1), ST
$01326C54 fld [rbx 8 +] qword
$01326C57 faddp ST(1), ST
$01326C59 fstp [rbx 8 +] qword
$01326C5C fld [rdi #16 +] qword
$01326C5F fld $01325D90 qword-offset
$01326C65 fmulp ST(1), ST
$01326C67 fld [rbx #16 +] qword
$01326C6A faddp ST(1), ST
$01326C6C fstp [rbx #16 +] qword
$01326C6F fld [rdi #24 +] qword
$01326C72 fld $01325D90 qword-offset
$01326C78 fmulp ST(1), ST
$01326C7A fld [rbx #24 +] qword
$01326C7D faddp ST(1), ST
$01326C7F fstp [rbx #24 +] qword
$01326C82 lea rdi, [rdi #32 +] qword
$01326C86 push rdi
$01326C87 lea rbx, [rbx #32 +] qword
$01326C8B add [rbp 0 +] qword, 1 b#
$01326C90 add [rbp 8 +] qword, 1 b#
$01326C95 jno $01326C38 offset NEAR
$01326C9B add rbp, #24 b#
$01326C9F pop rdi
$01326CA0 ;
-marcel
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-17 23:53 -0700 |
| Message-ID | <14adb3ac-9b58-47b7-9d76-954a42a787b9@googlegroups.com> |
| In reply to | #59432 |
2017. május 17., szerda 18:14:04 UTC+2 időpontban Anton Ertl a következőt írta:
> Performance: On a Core i7-4690K (no SwiftForth or iForth installed),
> with the unrolled versions:
>
> cycles
> Forth-2012 Forth-94 Forth-94
> Rees/Ertl pahihu
> 2929M 3691M 3480M gforth-fast
> 1289M 1414M 1574M vfxlin Ndp387
>
> Looks like a win for the Forth-2012 code to me.
My test was run on an i7-3630QM under Win7Pro 64bit. All times in milliseconds.
The SwiftForth version uses a modified fpmath.f which uses inlining:
\ SF3 iForth5 VFX4 gforth32 gforth64
\ 94-ertl 1100 464 310 2700 2090
\ 94-pahihu 1030 281 360 2620 1760
\ 20-ertl 870 281 297 2340 1760
For SwiftForth, VFX4 and gforth32 Forth-2012 wins, but for iForth5 and
gforth64 I don't see any advantage on this CPU and OS.
> VFX does not (yet?) analyse and optimize the return stack; or, if you
> feel nasty, you could say: it optimizes PICK better than >R R> and R@.
Agreed.
You write Forth code for a virtual stack machine, you use a particular
Forth compiler which translates the code to a register based CPU and you
run the code on a particular CPU and measure the cycles/times.
Using SwiftForth I checked how can I approach a baseline GCC 4.9.2 performance
(110/125 ms). The baseline was your Forth-2012 code (880 ms):
- using "F+!" instead of "DUP F@ F+ DUP F!" resulted in 660 ms
- using the code below I reached 520 ms
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
0 ?DO
fdup over I floats + f@ f* dup I floats + f+!
fdup over I 1+ floats + f@ f* dup I 1+ floats + f+!
fdup over I 2+ floats + f@ f* dup I 2+ floats + f+!
fdup over I 3 + floats + f@ f* dup I 3 + floats + f+!
4 +LOOP 2drop fdrop ;
- I added the DF@+ and DF+!+ primitives from iForth, this resulted in 290 ms
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
0 ?DO
fdup swap df@+ f* swap df+!+
fdup swap df@+ f* swap df+!+
fdup swap df@+ f* swap df+!+
fdup swap df@+ f* swap df+!+
4 +LOOP 2drop fdrop ;
- using the idea of Stephen Pelc from EuroForth 2008, I reached 140 ms
FA is a floating point pointer held in a register, >FA stores a
value from the data stack to the reg, FA@+ fetches a float using the
pointer and increments it
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
>R swap >FA R>
0 ?DO
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
4 +LOOP drop fdrop ;
- using FOR ... NEXT, loop counter in another register, resulted in 120 ms
OK, I cheated, because /NEXT decrements the counter by 4
: faxpy-nostride ( ra f_x f_y ucount -- )
\ vy=ra*vx+vy
>R swap >FA R>
FOR
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
fdup FA@+ f* df+!+
/NEXT drop fdrop ;
This final version which shines on i7 was just marginally better than the
original Forth-2012 code on a Core2 Duo 3.0GHz...
pahihu
[toc] | [prev] | [next] | [standalone]
| From | pahihu <pahihu@gmail.com> |
|---|---|
| Date | 2017-05-19 02:34 -0700 |
| Message-ID | <02b68980-120c-433c-91fd-004f81856552@googlegroups.com> |
| In reply to | #59463 |
2017. május 18., csütörtök 8:53:18 UTC+2 időpontban pahihu a következőt írta: > This final version which shines on i7 was just marginally better than the > original Forth-2012 code on a Core2 Duo 3.0GHz... Found it, was an alignment problem for the test arrays. (4bytes aligned instead of 8bytes) pahihu
[toc] | [prev] | [next] | [standalone]
| From | Joel Rees <joel.rees@gmail.com> |
|---|---|
| Date | 2017-05-16 22:48 -0700 |
| Message-ID | <a561c81c-8478-4528-ad63-7c3524bef94c@googlegroups.com> |
| In reply to | #59178 |
Sorry, Anton, I didn't know PICK was a Forth-94 thing, so I hadn't
read this until today.
On Sunday, May 14, 2017 at 12:29:04 AM UTC+9, 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.
>
> 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
Did I put this in a user variable?
If we don't want to see whether the compiler does a nice job with
constant expressions we could do this, instead:
2 CELLWIDTH * constant ra_offset
(I forget what you guys call CELLWIDTH.)
> : 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*
Thus,
over f@ ra_offset sp@ + f@ f*
or, if we had fPICK,
over f@ 2 fPICK f*
> FPCELLWIDTH pick f@ f+
> FPCELLWIDTH pick f!
> float+ swap float+ swap
> LOOP
> 2drop ;
I think I showed the high-level definition of fPICK:
: fPICK ( n -- f )
CELLWIDTH * sp@ + f@ ;
And I think I mumbled something about defining it low-level, instead.
> \ 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,
Indeed. gcc, too.
Reading the compiled C,
> gcc (faxpy)
(We aren't seeing the factor in %xmm0 get initialized.)
0x4180b8:
> movsd (%rdi),%xmm1
Grab the left-hand operand, store in FP register.
> add %rsi,%rdi
FP width in %rsi, so update left-hand operator pointer.
> mulsd %xmm0,%xmm1
FP multiply.
> addsd (%rdx),%xmm1
FP sum with right-hand.
> movsd %xmm1,(%rdx)
Store result to right-hand operand.
> add %rcx,%rdx
Update right-hand pointer.
This appears to be the with-stride version in C.
> sub $0x1,%r8
Count the loop.
> jne 0x4180b8 <faxpy+8>
---------------------
> VFX Forth-2012
080C6D78?
> FLD ST
Factor?
080C6D78?
> MOV EDX, [EBP]
> FLD TBYTE 0 [EDX]
Left-hand operand
> FMULP ST(1), ST
Product
> FLD TBYTE 0 [EBX]
> FADDP ST(1), ST
Sum with right-hand operand.
> FSTP TBYTE 0 [EBX]
Store to right-hand operand.
> ADD EBX, 0A
Update right-hand operand pointer.
> MOV EDX, [EBP]
For some reason, it has lost track of the left-hand operand pointer.
> ADD EDX, 0A
Update for left-hand operand pointer not complete.
> ADD [ESP], 01
Count the loop.
> ADD [ESP+04], 01
Outer loop? That would be a lot of code flattening going on.
> MOV [EBP], EDX
Left-hand operand now up-to-date.
> JNO 080C6D78
---------------------
> VFX Forth-94
080C6DB8:
> MOV EDX, [EBP]
Pointer to left-hand
> FLD TBYTE 0 [EDX]
Left-hand.
> FLD TBYTE [080A3460]
Factor.
> FMULP ST(1), ST
Product.
> FLD TBYTE 0 [EBX]
Right-hand.
> FADDP ST(1), ST
Sum with right-hand.
> FSTP TBYTE 0 [EBX]
Store result to right-hand operand.
> ADD EBX, 0A
Update right-hand pointer.
> MOV EDX, [EBP]
Again, for some reason, we have lost track of the left-hand pointer in EDX.
> ADD EDX, 0A
Incomplete update of left-hand pointer.
> ADD [ESP], 01
Loop counter.
> ADD [ESP+04], 01
Whatever this is.
> MOV [EBP], EDX
Complete update of left-hand pointer.
> JNO 080C6DB8
> and
> even the variable access does not cause an extra instruction.
Depends on where the start of the loop was, I think.
Also, there may be cache issues when the factor is not on a stack.
> 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.
If ST(1) is not aliased to a floating point register, I can see a good
reason for slowdown. I'm not sure if three times makes sense, but at
least double.
> 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.
I wouldn't think the size would be the issue.
> 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).
Interesting, but red-herring.
> 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.
True. The optimization is still just a shade short of the C optimization.
I get after the current troop of gcc maintainers, but they are getting
a bit better handle on how data migrates between registers and memory.
gcc output code is really tight.
> 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/
My conclusion is a little different, but I'm living in a dreamworld
where I can dream about building CPUs the way I think they should be
built.
I'd like to see what a conventional CPU (preferably not Intel) would
do with separate fast spill/fill cache for three stacks -- return,
parameter, and the alternate stack I'm suggesting; and conventional
fast cache for non-stack references.
The parameter and alternate stack caches could be peers to the
conventional fast cache between the CPU and the intermediate or slow
cache, but, for security, I'd like to keep the path to the return
cache clean and restrict access to it to access by the return stack
pointer.
--
Joel Rees
Delusions of reinventing the industry all by myself:
http://defining-computers.blogspot.com/
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-17 06:51 +0000 |
| Message-ID | <2017May17.085155@mips.complang.tuwien.ac.at> |
| In reply to | #59417 |
Joel Rees <joel.rees@gmail.com> writes:
>Sorry, Anton, I didn't know PICK was a Forth-94 thing, so I hadn't
>read this until today.
I am not sure what you mean by that. The "Forth-94" in the title
refers to the requirement that programs using FP words must work on
separate-stack systems and on combined-stack systems with any number
of cells per FP item.
>> 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
>
>Did I put this in a user variable?
No, you used a cell-based FPICK instead. FPICK is not a Forth-94
word, so I replaced your use of FPICK with a variable access.
Moreover, Gforth has an FPICK that uses the FP item index as input;
i.e., 1 FPICK is equivalent to FOVER; and I expect that other systems
providing FPICK work the same way.
>If we don't want to see whether the compiler does a nice job with
>constant expressions we could do this, instead:
>
>2 CELLWIDTH * constant ra_offset
>
>(I forget what you guys call CELLWIDTH.)
>
>> : 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*
>
>Thus,
>
> over f@ ra_offset sp@ + f@ f*
SP@ is not Forth-94, either.
>> So VFX works nicely for optimizing the PICKs, DUPs etc. away here,
>
>Indeed. gcc, too.
The source for the gcc faxpy code was a piece of C code (no PICKs or
DUPs), not Forth code.
>This appears to be the with-stride version in C.
Right.
>> VFX Forth-2012
>
>080C6D78?
>> FLD ST
>Factor?
fdup
I.e., yes, it's the RA parameter.
>> ADD [ESP], 01
>Count the loop.
Update I.
>> ADD [ESP+04], 01
>Outer loop? That would be a lot of code flattening going on.
Update max_n-limit+1+i. This, together with JNO, gives the wraparound
semantics for LOOP that is standard.
>Also, there may be cache issues when the factor is not on a stack.
The item is accessed so often that it stays in the cache.
>> 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.
>
>If ST(1) is not aliased to a floating point register, I can see a good
>reason for slowdown. I'm not sure if three times makes sense, but at
>least double.
ST(1) is a floating-point register.
- 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 | Joel Rees <joel.rees@gmail.com> |
|---|---|
| Date | 2017-05-17 09:29 -0700 |
| Message-ID | <4c48dc62-3942-4e45-9e4b-438b21693bb5@googlegroups.com> |
| In reply to | #59422 |
On Wednesday, May 17, 2017 at 7:14:00 PM UTC+9, Anton Ertl wrote: > Joel Rees <joel rees@somewhere> writes: > >Sorry, Anton, I didn't know PICK was a Forth-94 thing, so I hadn't > >read this until today. > > I am not sure what you mean by that. The "Forth-94" in the title > refers to the requirement that programs using FP words must work on > separate-stack systems and on combined-stack systems with any number > of cells per FP item. And I am completely oblivious to any requirements the standards impose. So we are, to a certain extent, talking past each other. > >> 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 > > > >Did I put this in a user variable? > > No, you used a cell-based FPICK instead. FPICK is not a Forth-94 > word, so I replaced your use of FPICK with a variable access. > Moreover, Gforth has an FPICK that uses the FP item index as input; > i.e., 1 FPICK is equivalent to FOVER; and I expect that other systems > providing FPICK work the same way. Okay, so FPICK was not the name to give it. I've been using LC@, but I think that is already defined by something else in gforth, too. > >If we don't want to see whether the compiler does a nice job with > >constant expressions we could do this, instead: > > > >2 CELLWIDTH * constant ra_offset > > > >(I forget what you guys call CELLWIDTH.) > > > >> : 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* > > > >Thus, > > > > over f@ ra_offset sp@ + f@ f* > > SP@ is not Forth-94, either. But it is defined in gforth. Still, I'd define the PICK-like access word in assembler before trying benchmark, I think. It makes absolutely no sense not to be able, when code calls for it, to access memory at a fairly arbitrary offset from a stack pointer. > >> So VFX works nicely for optimizing the PICKs, DUPs etc. away here, > > > >Indeed. gcc, too. > > The source for the gcc faxpy code was a piece of C code (no PICKs or > DUPs), not Forth code. I didn't realize I was implying otherwise. > >This appears to be the with-stride version in C. > > Right. > > >> VFX Forth-2012 > > > >080C6D78? > >> FLD ST > >Factor? > > fdup > > I.e., yes, it's the RA parameter. > > >> ADD [ESP], 01 > >Count the loop. > > Update I. > > >> ADD [ESP+04], 01 > >Outer loop? That would be a lot of code flattening going on. > > Update max_n-limit+1+i. This, together with JNO, gives the wraparound > semantics for LOOP that is standard. I'll have to think that one through. > >Also, there may be cache issues when the factor is not on a stack. > > The item is accessed so often that it stays in the cache. If the cache line it's on isn't bumped ... > >> 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. > > > >If ST(1) is not aliased to a floating point register, I can see a good > >reason for slowdown. I'm not sure if three times makes sense, but at > >least double. > > ST(1) is a floating-point register. That shoots that theory. > - 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/ -- Joel Rees Delusions of being a novelist: http://joel-rees-economics.blogspot.com/2017/01/soc500-00-00-toc.html
[toc] | [prev] | [next] | [standalone]
| From | stephen@mpeforth.com (Stephen Pelc) |
|---|---|
| Date | 2017-05-17 11:07 +0000 |
| Message-ID | <591c2dab.599913139@news.eternal-september.org> |
| In reply to | #59417 |
On Tue, 16 May 2017 22:48:04 -0700 (PDT), Joel Rees <joel.rees@gmail.com> wrote: >> 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, Note also that ?DO ... LOOP is not optimal here as it maintains two items in memory. See the last four instructions in the VFX listings. A simple BEGIN ... UNTIL may be better. In general, DO LOOP is only optimal if the loop count is used more than once on register-starved CPUs. If you have 16 or more registers using two for DO ... LOOP may be more effective. Measurement will prove it when we ave the time and resources. Stephen -- Stephen Pelc, stephenXXX@mpeforth.com MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2017-05-17 15:02 +0000 |
| Message-ID | <2017May17.170216@mips.complang.tuwien.ac.at> |
| In reply to | #59423 |
stephen@mpeforth.com (Stephen Pelc) writes:
>On Tue, 16 May 2017 22:48:04 -0700 (PDT), Joel Rees
><joel.rees@gmail.com> wrote:
>
>>> 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,
>
>Note also that ?DO ... LOOP is not optimal here as it maintains two
>items in memory. See the last four instructions in the VFX listings.
>A simple BEGIN ... UNTIL may be better.
There is nothing in ?DO...LOOP that prevents a compiler from
generating as good code for it as from BEGIN...WHILE...REPEAT
(BEGIN...UNTIL would be more appropriate for DO...LOOP). Moreover,
DO...LOOP is a way to reduce stack load, and is therefore usually
preferred by programmers when they program counted loops. But you can
try to convince me otherwise
> If you have 16 or more registers
>using two for DO ... LOOP may be more effective.
My suggestion is to use one register (containing the index) and one
memory location (containing the limit) on Intel/AMD CPUs, even with
only 8 registers. I.e., something like:
inc ecx
cmp ecx, [esp]
jne right-after-do
This means that you can LOOP at up to one iteration per cycle (instead
of 1 per 5 or 6 cycles with the current scheme). You may worry about
the [esp] memory access, but it does not depend on anything in the
loop, so it can be executed early by out-of-order execution. And if
you don't put anything else between the cmp and the jne, recent Intel
CPUs will combine (macro-fuse) them, reducing resource consumption,
and maybe increasing performance.
Anyway, as I described in the posting, I unrolled the loop (by a
factor of 4) to reduce the impact of loop overhead.
- 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] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.forth
csiph-web