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


Groups > comp.lang.forth > #29696 > unrolled thread

Epic fail

Started byRob Sciuk <rob@controlq.com>
First post2014-04-17 17:35 -0400
Last post2014-04-20 12:00 +0000
Articles 6 — 4 participants

Back to article view | Back to comp.lang.forth


Contents

  Epic fail Rob Sciuk <rob@controlq.com> - 2014-04-17 17:35 -0400
    Re: Epic fail Bernd Paysan <bernd.paysan@gmx.de> - 2014-04-17 23:55 +0200
    Re: Epic fail anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-04-18 17:27 +0000
      Re: Epic fail Rob Sciuk <rob@controlq.com> - 2014-04-18 14:54 -0400
        Re: Epic fail albert@spenarnc.xs4all.nl (Albert van der Horst) - 2014-04-19 11:53 +0000
        Re: Epic fail anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-04-20 12:00 +0000

#29696 — Epic fail

FromRob Sciuk <rob@controlq.com>
Date2014-04-17 17:35 -0400
SubjectEpic fail
Message-ID<alpine.BSF.2.00.1404171716050.71902@yoko.controlq.com>

With little consideration for optimization, other than the -Ofast flag on 
the gcc command, MiniForth is 83.2% the speed of of Gforth 0.7.2 on a 
Linux I7 box (time measured in usecs in both cases).

I consider this a big win for the MiniForth approach, as performance has 
always taken a back seat to portability.  Nonetheless, should Gforth move 
to a different compilation methodology, I'd be very interested in knowing 
the approach taken, as the rationale has been adequately explained.

Gforth remains a remarkable achievment with respect to its portability, 
coupled with exceptional speed for a C based forth.

Cheers,
Rob.



bash-3.2$ ./mff
-- MiniForth-Hosted alpha Version: 00.01.25F
-- www.ControlQ.com
ok : x 0 begin 1 + 0xfffff over > while dup drop spin repeat drop ;
ok usec x usec swap - .
4148068 ok usec x usec swap - .
4165781 ok usec x usec swap - .
4172488 ok usec x usec swap - .
4195942 ok usec x usec swap - .
4167564 ok
ok
ok usec x usec swap - .
4145503 ok bye
bash-3.2$ gforth
Gforth 0.7.2, Copyright (C) 1995-2008 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
: spin 33 emit 13 emit ;  ok
: x 0 begin 1+ 0xfffff over > while dup drop spin repeat drop ;   ok
3336340  okme 2swap d- d. !
3353832  okme 2swap d- d. !
3699813  okme 2swap d- d. !
3774070  okme 2swap d- d. !
3342879  okme 2swap d- d. !
3318600  okme 2swap d- d. !
see x
: x
   0
   BEGIN  1+ 1048575 over >
   WHILE  dup drop spin
   REPEAT
   drop ; ok

[toc] | [next] | [standalone]


#29697

FromBernd Paysan <bernd.paysan@gmx.de>
Date2014-04-17 23:55 +0200
Message-ID<lipik1$244$1@online.de>
In reply to#29696
Rob Sciuk wrote:
> Gforth remains a remarkable achievment with respect to its portability,
> coupled with exceptional speed for a C based forth.

And you even didn't use gforth-fast for your benchmarks ;-).

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#29710

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2014-04-18 17:27 +0000
Message-ID<2014Apr18.192721@mips.complang.tuwien.ac.at>
In reply to#29696
Rob Sciuk <rob@controlq.com> writes:
>
>
>With little consideration for optimization, other than the -Ofast flag on 
>the gcc command, MiniForth is 83.2% the speed of of Gforth 0.7.2 on a 
>Linux I7 box (time measured in usecs in both cases).

Here's the program

: spin 33 emit 13 emit ;
: x 0 begin 1+ 0xfffff over > while dup drop spin repeat drop ;

It seems to me that the majority of the run-time will be spent in
EMIT.  I am surprised that there is such a large difference there, but
that difference is probably based on the way that EMIT is implemented,
not on the way the rest of the Forth system is implemented.

>I consider this a big win for the MiniForth approach, as performance has 
>always taken a back seat to portability.  Nonetheless, should Gforth move 
>to a different compilation methodology, I'd be very interested in knowing 
>the approach taken, as the rationale has been adequately explained.

Native code for the popular platforms, and probably a fallback based
on C for the rest (which may become several times slower than it is
now as we turn off performance features when the C compilers break
them).

- 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 2013: http://www.euroforth.org/ef13/

[toc] | [prev] | [next] | [standalone]


#29712

FromRob Sciuk <rob@controlq.com>
Date2014-04-18 14:54 -0400
Message-ID<alpine.BSF.2.00.1404181447300.40766@yoko.controlq.com>
In reply to#29710
On Fri, 18 Apr 2014, Anton Ertl wrote:

> Date: Fri, 18 Apr 2014 17:27:21 GMT
> From: Anton Ertl <anton@mips.complang.tuwien.ac.at>
> Newsgroups: comp.lang.forth
> Subject: Re: Epic fail
> 
> Rob Sciuk <rob@controlq.com> writes:
>>
>>
>> With little consideration for optimization, other than the -Ofast flag on
>> the gcc command, MiniForth is 83.2% the speed of of Gforth 0.7.2 on a
>> Linux I7 box (time measured in usecs in both cases).
>
> Here's the program
>
> : spin 33 emit 13 emit ;
> : x 0 begin 1+ 0xfffff over > while dup drop spin repeat drop ;
>
> It seems to me that the majority of the run-time will be spent in
> EMIT.  I am surprised that there is such a large difference there, but
> that difference is probably based on the way that EMIT is implemented,
> not on the way the rest of the Forth system is implemented.
>

Ahh, quite so, Anton.  With the spin (i/o) removed, the gforth is an order 
of magnitude faster than MiniForth, but of course, there is no forth 
optimization done on MiniForth.  Still, this speaks very well for the 
implementation methodology used for Gforth.

BTW: does Gforth optimize sequences such as "dup drop" => NOOP?

Cheers,
Rob.

[toc] | [prev] | [next] | [standalone]


#29720

Fromalbert@spenarnc.xs4all.nl (Albert van der Horst)
Date2014-04-19 11:53 +0000
Message-ID<535263b8$0$27148$e4fe514c@dreader35.news.xs4all.nl>
In reply to#29712
In article <alpine.BSF.2.00.1404181447300.40766@yoko.controlq.com>,
Rob Sciuk  <rob@controlq.com> wrote:
>On Fri, 18 Apr 2014, Anton Ertl wrote:
>
>> Date: Fri, 18 Apr 2014 17:27:21 GMT
>> From: Anton Ertl <anton@mips.complang.tuwien.ac.at>
>> Newsgroups: comp.lang.forth
>> Subject: Re: Epic fail
>>
>> Rob Sciuk <rob@controlq.com> writes:
>>>
>>>
>>> With little consideration for optimization, other than the -Ofast flag on
>>> the gcc command, MiniForth is 83.2% the speed of of Gforth 0.7.2 on a
>>> Linux I7 box (time measured in usecs in both cases).
>>
>> Here's the program
>>
>> : spin 33 emit 13 emit ;
>> : x 0 begin 1+ 0xfffff over > while dup drop spin repeat drop ;
>>
>> It seems to me that the majority of the run-time will be spent in
>> EMIT.  I am surprised that there is such a large difference there, but
>> that difference is probably based on the way that EMIT is implemented,
>> not on the way the rest of the Forth system is implemented.
>>
>
>Ahh, quite so, Anton.  With the spin (i/o) removed, the gforth is an order
>of magnitude faster than MiniForth, but of course, there is no forth
>optimization done on MiniForth.  Still, this speaks very well for the
>implementation methodology used for Gforth.
>
>BTW: does Gforth optimize sequences such as "dup drop" => NOOP?

I read it different from Anton. I thought the benchmark was
intended to measure the speed of EMIT.

If I leave out spin, a well designed optimiser will not only conclude that
it can leave out 'dup drop' but the whole loop.
The loop is a code sequence with the property
that it has no side effects, so because its results are dropped,
the whole loop can be omitted.
Even if the result was not dropped, the optimiser can
execute the sequence at compile time. It will do so and
leave no run time to speak off.

See,
http://home.hccnet.nl/a.w.m.van.der.horst/forthlecture5.html

The art of benchmarking is treacherous.

>
>Cheers,
>Rob.
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

[toc] | [prev] | [next] | [standalone]


#29730

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2014-04-20 12:00 +0000
Message-ID<2014Apr20.140052@mips.complang.tuwien.ac.at>
In reply to#29712
Rob Sciuk <rob@controlq.com> writes:
>BTW: does Gforth optimize sequences such as "dup drop" => NOOP?

No.  There are two optimizations that might achieve this, but in
Gforth don't:

1) Static superinstruction, where certain sequences of primitives are
replaced by optimized composite primitives (superinstructions).  We
are optimizing IIRC 13 frequently-occuring sequences, e.g., LIT +, but
DUP DROP is not such a sequence.

2) Static stack caching: There are several versions of
frequently-occuring primitives, for different representations of the
stack.

E.g., consider "DROP 1": We start out with the canonical stack
representation (S1) of one item in a register, and the stack pointer
pointing to the next item.  We have another stack representation (S0)
where there is no stack item in a register and the stack pointer
points to the top item, which is in memory.  A DROP that goes from S1
to S0 is really cheap, almost a noop.  A LIT that goes from S0 to S1
is also quite cheap.  So Gforth chooses to use S0 as stack
representation between the DROP and the LIT:

: foo drop 1 ; see-code foo 
$7F07B4266088 noop
   0x00007f07b59e8af9:  add    $0x8,%rbp
$7F07B4266090 lit
$7F07B4266098 <1> 
   0x00007f07b59e8afd:  mov    0x0(%rbp),%r14
   0x00007f07b59e8b01:  add    $0x10,%rbp
$7F07B42660A0 ;s ok

Apart from the instruction pointer updates (the adds to %rbp), there
is only one instruction in this sequence.

However, static stack caching as implemented in Gforth does not
optimize DUP DROP into a noop, because Gforth has no state that
represents a DUPed top-of-stack.

On PowerPC, the sequence DUP DROP can be optimized better, but not
into a noop; there we have stack representations with more than one
register (more registers are usable), in particular S2, where the top
two stack items are in registers.  A DUP from S1 to S2 is just a move
instruction, and a DROP from S2 to S1 is a noop, so on PowerPC this
sequence would be optimized into a move plus two IP updates.

- 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 2013: http://www.euroforth.org/ef13/

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.forth


csiph-web