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


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

CMOVE/CMOVE>

Started byMark Wills <markwills1970@gmail.com>
First post2015-08-18 08:44 -0700
Last post2015-08-19 02:58 +0200
Articles 20 on this page of 30 — 12 participants

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


Contents

  CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-18 08:44 -0700
    Re: CMOVE/CMOVE> anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-08-18 16:05 +0000
      Re: CMOVE/CMOVE> november.nihal@gmail.com - 2015-08-18 09:34 -0700
        Re: CMOVE/CMOVE> anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-08-18 16:41 +0000
      Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-18 09:59 -0700
        Re: CMOVE/CMOVE> Michael Barry <barrym95838@yahoo.com> - 2015-08-18 10:10 -0700
          Re: CMOVE/CMOVE> hughaguilar96@gmail.com - 2015-08-18 10:41 -0700
            Re: CMOVE/CMOVE> "Alex McDonald" <blog@rivadpm.com> - 2015-08-18 23:55 +0100
              Re: CMOVE/CMOVE> anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-08-19 08:40 +0000
                Re: CMOVE/CMOVE> "Alex McDonald" <blog@rivadpm.com> - 2015-08-19 12:15 +0100
          Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-18 11:35 -0700
            Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-18 11:36 -0700
              Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-20 04:39 +1000
            Re: CMOVE/CMOVE> "Elizabeth D. Rather" <erather@forth.com> - 2015-08-19 09:15 -1000
            Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-28 22:39 +1000
              Re: CMOVE/CMOVE> Coos Haak <chforth@hccnet.nl> - 2015-08-28 15:06 +0200
                Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-29 17:15 +1000
                  Re: CMOVE/CMOVE> Coos Haak <chforth@hccnet.nl> - 2015-08-29 13:24 +0200
                    Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-31 11:38 +1000
                  Re: CMOVE/CMOVE> "Elizabeth D. Rather" <erather@forth.com> - 2015-08-29 07:59 -1000
                    Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-30 13:00 +1000
              Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-28 07:33 -0700
              Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-28 07:36 -0700
                Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-29 02:23 +1000
              Re: CMOVE/CMOVE> mhx@iae.nl - 2015-08-28 11:41 -0700
                Re: CMOVE/CMOVE> "HAA" <someone@microsoft.com> - 2015-08-29 17:30 +1000
          Re: CMOVE/CMOVE> anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2015-08-19 08:04 +0000
        Re: CMOVE/CMOVE> "Rod Pemberton" <boo@fasdfrewar.cdm> - 2015-08-19 02:48 -0400
          Re: CMOVE/CMOVE> Mark Wills <markwills1970@gmail.com> - 2015-08-19 00:49 -0700
      Re: CMOVE/CMOVE> Bernd Paysan <bernd.paysan@gmx.de> - 2015-08-19 02:58 +0200

Page 1 of 2  [1] 2  Next page →


#41372 — CMOVE/CMOVE>

FromMark Wills <markwills1970@gmail.com>
Date2015-08-18 08:44 -0700
SubjectCMOVE/CMOVE>
Message-ID<62627f57-1e63-4156-844a-db5708923aaf@googlegroups.com>
I'm aware of the word MOVE which will choose to perform either a CMOVE or CMOVE> depending on overlap and direction. My system doesn't have MOVE though I'd like to implement it.

Does anyone have any nice concise logic for checking the parameters and calling either CMOVE or CMOVE> accordingly?

Many thanks

Mark

[toc] | [next] | [standalone]


#41375

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-08-18 16:05 +0000
Message-ID<2015Aug18.180551@mips.complang.tuwien.ac.at>
In reply to#41372
Mark Wills <markwills1970@gmail.com> writes:
>I'm aware of the word MOVE which will choose to perform either a CMOVE or CMOVE> depending on overlap and direction. My system doesn't have MOVE though I'd like to implement it.
>
>Does anyone have any nice concise logic for checking the parameters and calling either CMOVE or CMOVE> accordingly?

: move ( from to count -- )
  >r 2dup u< if
    r> cmove>
  else
    r> cmove
  then ;

Better branch prediction accuracy:

: move ( from to count -- )
  >r 2dup dup r@ + within if
    r> cmove
  else
    r> cmove>
  then ;

Both not tested.

- 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 2015: http://www.mpeforth.com/euroforth2015/euroforth2015.htm

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


#41376

Fromnovember.nihal@gmail.com
Date2015-08-18 09:34 -0700
Message-ID<ba32a33b-cf92-46fa-9162-77ca74c8bec4@googlegroups.com>
In reply to#41375
for the second example ; 

shouldn't that be :  >r 2dup over r@ + within if ( from + count ) ?

NN

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


#41377

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-08-18 16:41 +0000
Message-ID<2015Aug18.184133@mips.complang.tuwien.ac.at>
In reply to#41376
november.nihal@gmail.com writes:
>
>for the second example ; 
>
>shouldn't that be :  >r 2dup over r@ + within if ( from + count ) ?

My idea was to test whether FROM is within [TO, TO+COUNT), so I think
my version is right.  Other variations are also possible, of course.

- 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 2015: http://www.mpeforth.com/euroforth2015/euroforth2015.htm

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


#41378

FromMark Wills <markwills1970@gmail.com>
Date2015-08-18 09:59 -0700
Message-ID<c3289222-a562-44db-a30a-1f8d58d0fc6b@googlegroups.com>
In reply to#41375
On Tuesday, 18 August 2015 17:16:28 UTC+1, Anton Ertl  wrote:
> Mark Wills <markwills1970@gmail.com> writes:
> >I'm aware of the word MOVE which will choose to perform either a CMOVE or CMOVE> depending on overlap and direction. My system doesn't have MOVE though I'd like to implement it.
> >
> >Does anyone have any nice concise logic for checking the parameters and calling either CMOVE or CMOVE> accordingly?
> 
> : move ( from to count -- )
>   >r 2dup u< if
>     r> cmove>
>   else
>     r> cmove
>   then ;
> 
> Better branch prediction accuracy:
> 
> : move ( from to count -- )
>   >r 2dup dup r@ + within if
>     r> cmove
>   else
>     r> cmove>
>   then ;
> 
> Both not tested.
> 
> - 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 2015: http://www.mpeforth.com/euroforth2015/euroforth2015.htm

That's nice code, thank you. Mine also included WITHIN but your first 
example is neater IMO. I just tested it quickly and it seems to work fine.

Thanks.

Mark

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


#41379

FromMichael Barry <barrym95838@yahoo.com>
Date2015-08-18 10:10 -0700
Message-ID<cc2c79a3-48ce-400e-b3b6-4474c9c47917@googlegroups.com>
In reply to#41378
On Tuesday, August 18, 2015 at 9:59:02 AM UTC-7, Mark Wills wrote:
> 
> > : move ( from to count -- )
> >   >r 2dup u< if
> >     r> cmove>
> >   else
> >     r> cmove
> >   then ;
> > 
> > Better branch prediction accuracy:
> > 
> > : move ( from to count -- )
> >   >r 2dup dup r@ + within if
> >     r> cmove
> >   else
> >     r> cmove>
> >   then ;
> > 
> > Both not tested.
> > 
> > - anton
> > -- 
> >
>  
> That's nice code, thank you. Mine also included WITHIN but your first 
> example is neater IMO. I just tested it quickly and it seems to work fine.
> 
> Thanks.
> 
> Mark

Isn't it true that the decision can be made based simply on whether source start is less than destination start, regardless of count?  Mine does that, but CMOVE> and CMOVE have equivalent performance, which might mot always be the case.

[code]

;----------- 65m32: smart move --------
; Move memory up/down (1 W to 4 GW)
; x = source start address
; y = destination start address
; b = number of words to move
; (4 GW are moved if b == 0 !!)
;
:88020000 move:   cpy  #,x
:42420000 mvdown: lda  [cc],x+
:a2440000         sta  [cc],y+
:8c49fffd         dbn  [cc]mvdown,b
:5e4c0000         rts  [cc]
:e4080000         adx  #,b
:e8080000         ady  #,b
:43020000 moveup: lda  ,-x
:a3040000         sta  ,-y
:8c09fffd         dbn  moveup,b
:5e0c0000         rts
[/code]

Mike B.

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


#41380

Fromhughaguilar96@gmail.com
Date2015-08-18 10:41 -0700
Message-ID<70231de3-da52-405a-a20d-a578e9783f12@googlegroups.com>
In reply to#41379
On Tuesday, August 18, 2015 at 10:10:22 AM UTC-7, Michael Barry wrote:
> On Tuesday, August 18, 2015 at 9:59:02 AM UTC-7, Mark Wills wrote:
> > 
> > > : move ( from to count -- )
> > >   >r 2dup u< if
> > >     r> cmove>
> > >   else
> > >     r> cmove
> > >   then ;
> > > 
> > > Better branch prediction accuracy:
> > > 
> > > : move ( from to count -- )
> > >   >r 2dup dup r@ + within if
> > >     r> cmove
> > >   else
> > >     r> cmove>
> > >   then ;
> > > 
> > > Both not tested.
> > > 
> > > - anton
> > > -- 
> > >
> >  
> > That's nice code, thank you. Mine also included WITHIN but your first 
> > example is neater IMO. I just tested it quickly and it seems to work fine.
> > 
> > Thanks.
> > 
> > Mark
> 
> Isn't it true that the decision can be made based simply on whether source start is less than destination start, regardless of count?  Mine does that, but CMOVE> and CMOVE have equivalent performance, which might mot always be the case.

Yes, it is only necessary to compare the start addresses.

Checking the count to determine if CMOVE> is strictly necessary presumes that CMOVE> should be avoided as much as possible. I don't really know why there would be any difference in speed on any processor though. There is a slight overhead with CMOVE> in that you have to add the counts to the start-addresses to obtain the limit-addresses, but that is done only once and should be over-shadowed by the time needed to do all the moves.

It would be a good idea to have a MOVE that is only for structs whose size is a cell-multiple (this is always true in the novice-package because FIELD cell-aligns the fields in a struct). 

It would also be a good idea to have an EXCHANGE like I do in the novice-package (but it is very slow when written in Forth rather than assembly-language). Note that mine assumes that the struct size is a cell-multiple.

Anyway --- none of these good ideas will be in Forth-200x --- at least, not unless Leon Wagner says so.

> [code]
> 
> ;----------- 65m32: smart move --------
> ; Move memory up/down (1 W to 4 GW)
> ; x = source start address
> ; y = destination start address
> ; b = number of words to move
> ; (4 GW are moved if b == 0 !!)
> ;
> :88020000 move:   cpy  #,x
> :42420000 mvdown: lda  [cc],x+
> :a2440000         sta  [cc],y+
> :8c49fffd         dbn  [cc]mvdown,b
> :5e4c0000         rts  [cc]
> :e4080000         adx  #,b
> :e8080000         ady  #,b
> :43020000 moveup: lda  ,-x
> :a3040000         sta  ,-y
> :8c09fffd         dbn  moveup,b
> :5e0c0000         rts
> [/code]
> 
> Mike B.

Oh, I just noticed that your code does move cells. I think you mentioned that you don't have byte-addressing.

Why don't you publish a document describing your 65m32 similar to my document describing the FMITE processor? Nobody knows what any of those instructions do. BTW: does the 'm' in 65m32 stand for "Michael"?

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


#41385

From"Alex McDonald" <blog@rivadpm.com>
Date2015-08-18 23:55 +0100
Message-ID<mr0d1a$ke7$1@dont-email.me>
In reply to#41380
on 18/08/2015 18:41:19,  wrote:
> > On Tuesday, August 18, 2015 at 10:10:22 AM UTC-7, Michael Barry wrote:

>>
>> Isn't it true that the decision can be made based simply on whether sourc
> e start is less than destination start, regardless of count? Mine does
> tha t, but CMOVE> and CMOVE have equivalent performance, which might
> mot always be the case.
> 
> Yes, it is only necessary to compare the start addresses.

No, because if there's an overlap then there may be advantages in using
larger than CHAR sized moves. When there is an overlap, CMOVE> should
always do a character by character move (for instance, on the x86 REP
MOVS BYTE); otherwise much larger units can be CMOVE>d if there is no
overlap (REP MOVS DWORD or QWORD or MOVDQU thru XMM registers, etc). The
difference in performance can be considerable. 




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


#41396

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2015-08-19 08:40 +0000
Message-ID<2015Aug19.104049@mips.complang.tuwien.ac.at>
In reply to#41385
"Alex McDonald" <blog@rivadpm.com> writes:
>on 18/08/2015 18:41:19,  wrote:
>> > On Tuesday, August 18, 2015 at 10:10:22 AM UTC-7, Michael Barry wrote:
>
>>>
>>> Isn't it true that the decision can be made based simply on whether sourc
>> e start is less than destination start, regardless of count? Mine does
>> tha t, but CMOVE> and CMOVE have equivalent performance, which might
>> mot always be the case.
>> 
>> Yes, it is only necessary to compare the start addresses.
>
>No, because if there's an overlap then there may be advantages in using
>larger than CHAR sized moves. When there is an overlap, CMOVE> should
>always do a character by character move (for instance, on the x86 REP
>MOVS BYTE); otherwise much larger units can be CMOVE>d if there is no
>overlap (REP MOVS DWORD or QWORD or MOVDQU thru XMM registers, etc). The
>difference in performance can be considerable.

If you implement MOVE, you can use larger granularity for either
direction (of course, you need to take care of the remainder at the
start and/or end).  I would hope that on an IA-32/AMD64 CPU the CPU
does that for you if you use REP MOVSB and the parameters are
appropriate.  Unfortunately, it seems that doing it in software is
faster, at least for microbenchmarks, and this has lead to glibc's
memmove() having 11KB of code.  This is likely to be slower in
applications due to I-cache misses, but as long as it produces good
microbenchmark results...

Even for CMOVE or CMOVE> you can usually use a larger granularity even
for the overlap case; the granularity for CMOVE must just be at most
TO-FROM for CMOVE and FROM-TO for CMOVE>.

- 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 2015: http://www.mpeforth.com/euroforth2015/euroforth2015.htm

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


#41397

From"Alex McDonald" <blog@rivadpm.com>
Date2015-08-19 12:15 +0100
Message-ID<mr1oe9$m8m$1@dont-email.me>
In reply to#41396
on 19/08/2015 09:40:45,  wrote:
> "Alex McDonald" <blog@rivadpm.com> writes:
>>on 18/08/2015 18:41:19,  wrote:
>>> > On Tuesday, August 18, 2015 at 10:10:22 AM UTC-7, Michael Barry wrote:
>>
>>>>
>>>> Isn't it true that the decision can be made based simply on whether sourc
>>> e start is less than destination start, regardless of count? Mine does
>>> tha t, but CMOVE> and CMOVE have equivalent performance, which might
>>> mot always be the case.
>>>
>>> Yes, it is only necessary to compare the start addresses.
>>
>>No, because if there's an overlap then there may be advantages in using

s/there's an overlap/there's not an overlap/ but you got my drift.

>>larger than CHAR sized moves. When there is an overlap, CMOVE> should
>>always do a character by character move (for instance, on the x86 REP
>>MOVS BYTE); otherwise much larger units can be CMOVE>d if there is no
>>overlap (REP MOVS DWORD or QWORD or MOVDQU thru XMM registers, etc). The
>>difference in performance can be considerable.
> 
> If you implement MOVE, you can use larger granularity for either
> direction (of course, you need to take care of the remainder at the
> start and/or end).  I would hope that on an IA-32/AMD64 CPU the CPU
> does that for you if you use REP MOVSB and the parameters are
> appropriate.  Unfortunately, it seems that doing it in software is
> faster, at least for microbenchmarks, and this has lead to glibc's
> memmove() having 11KB of code.  This is likely to be slower in
> applications due to I-cache misses, but as long as it produces good
> microbenchmark results...

On further reading, it appears that (for instance, the Intel Haswell) REP
MOVS BYTE is optimised iif both source and dest are aligned to 32 bytes.
http://www.agner.org/optimize/microarchitecture.pdf pg 142 where it
recommends 256 bit registers otherwise. The net is full of contrarian
advice and equally varied code.

This is BSD's memmove()
http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/lib/libkern/arch/amd64/memmove.S?rev=1.5&content-type=text/plain
It's much shorter and the very paragon of simplicity compared to the
glibc version.

My CMOVE CMOVE> use MOVS BYTE; MOVE uses MOVS DWORD for the bulk word
aligned and MOVS BYTE for the remaining top and tail. I wrote a bulk copy
based on MOVDQU. I haven't benchmarked it properly, but it was marginally
but measurably faster than MOVE for large blocks.

> 
> Even for CMOVE or CMOVE> you can usually use a larger granularity even
> for the overlap case; the granularity for CMOVE must just be at most
> TO-FROM for CMOVE and FROM-TO for CMOVE>.

Point taken; the overlap still needs checked to do so.
 
> 
> - anton

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


#41381

FromMark Wills <markwills1970@gmail.com>
Date2015-08-18 11:35 -0700
Message-ID<c4beff92-d7da-4b6c-a37a-b40478fd914f@googlegroups.com>
In reply to#41379
On Tuesday, 18 August 2015 18:10:22 UTC+1, Michael Barry  wrote:
> On Tuesday, August 18, 2015 at 9:59:02 AM UTC-7, Mark Wills wrote:
> > 
> > > : move ( from to count -- )
> > >   >r 2dup u< if
> > >     r> cmove>
> > >   else
> > >     r> cmove
> > >   then ;
> > > 
> > > Better branch prediction accuracy:
> > > 
> > > : move ( from to count -- )
> > >   >r 2dup dup r@ + within if
> > >     r> cmove
> > >   else
> > >     r> cmove>
> > >   then ;
> > > 
> > > Both not tested.
> > > 
> > > - anton
> > > -- 
> > >
> >  
> > That's nice code, thank you. Mine also included WITHIN but your first 
> > example is neater IMO. I just tested it quickly and it seems to work fine.
> > 
> > Thanks.
> > 
> > Mark
> 
> Isn't it true that the decision can be made based simply on whether source start is less than destination start, regardless of count?  Mine does that, but CMOVE> and CMOVE have equivalent performance, which might mot always be the case.
> 
> [code]
> 
> ;----------- 65m32: smart move --------
> ; Move memory up/down (1 W to 4 GW)
> ; x = source start address
> ; y = destination start address
> ; b = number of words to move
> ; (4 GW are moved if b == 0 !!)
> ;
> :88020000 move:   cpy  #,x
> :42420000 mvdown: lda  [cc],x+
> :a2440000         sta  [cc],y+
> :8c49fffd         dbn  [cc]mvdown,b
> :5e4c0000         rts  [cc]
> :e4080000         adx  #,b
> :e8080000         ady  #,b
> :43020000 moveup: lda  ,-x
> :a3040000         sta  ,-y
> :8c09fffd         dbn  moveup,b
> :5e0c0000         rts
> [/code]
> 
> Mike B.

I think so, yes.

I just knocked this up to move blocks around. It's for my hobby Forth
system running on antiquated (>30 years old) hardware. Think 5.25" 
floppies and you're in the ball park.

It uses locals. From some quick experiments, locals on a dumb (non-
optimising) ITC makes things faster. The reason? All the stack juggling
goes away. Those ROTs DUPs SWAPs etc are burning up time just getting 
the stack arranged. Locals on a dumb system takes that away. The
argument doesn't hold on modern optimising systems.

Anyway, it's moot... The disk I/O is millions of times slower than
the code! But locals sure makes it easy... Like falling of a log.

Ignore FLUSH? It just checks the block buffers and one or more is
not flushed (dirty?) it offers the choice to do a flush first.

: movblk ( src dest cnt -- )
  locals{ src dest cnt cpydir }
  set cnt   set dest   set src 
  src dest < if
    cnt 1- +set src
    cnt 1- +set dest
    -1 set cpydir 
  else
    1 set cpydir
  then flush? 
  cnt 0 do
    2 spaces src . ." to " dest .
    src block drop  0 dest setblk  0 dirty flush
    cpydir +set src   
    cpydir +set dest
  loop ;

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


#41382

FromMark Wills <markwills1970@gmail.com>
Date2015-08-18 11:36 -0700
Message-ID<277a4458-52c2-4bbc-a068-f862ceaf4358@googlegroups.com>
In reply to#41381
On Tuesday, 18 August 2015 19:35:58 UTC+1, Mark Wills  wrote:
> On Tuesday, 18 August 2015 18:10:22 UTC+1, Michael Barry  wrote:
> > On Tuesday, August 18, 2015 at 9:59:02 AM UTC-7, Mark Wills wrote:
> > > 
> > > > : move ( from to count -- )
> > > >   >r 2dup u< if
> > > >     r> cmove>
> > > >   else
> > > >     r> cmove
> > > >   then ;
> > > > 
> > > > Better branch prediction accuracy:
> > > > 
> > > > : move ( from to count -- )
> > > >   >r 2dup dup r@ + within if
> > > >     r> cmove
> > > >   else
> > > >     r> cmove>
> > > >   then ;
> > > > 
> > > > Both not tested.
> > > > 
> > > > - anton
> > > > -- 
> > > >
> > >  
> > > That's nice code, thank you. Mine also included WITHIN but your first 
> > > example is neater IMO. I just tested it quickly and it seems to work fine.
> > > 
> > > Thanks.
> > > 
> > > Mark
> > 
> > Isn't it true that the decision can be made based simply on whether source start is less than destination start, regardless of count?  Mine does that, but CMOVE> and CMOVE have equivalent performance, which might mot always be the case.
> > 
> > [code]
> > 
> > ;----------- 65m32: smart move --------
> > ; Move memory up/down (1 W to 4 GW)
> > ; x = source start address
> > ; y = destination start address
> > ; b = number of words to move
> > ; (4 GW are moved if b == 0 !!)
> > ;
> > :88020000 move:   cpy  #,x
> > :42420000 mvdown: lda  [cc],x+
> > :a2440000         sta  [cc],y+
> > :8c49fffd         dbn  [cc]mvdown,b
> > :5e4c0000         rts  [cc]
> > :e4080000         adx  #,b
> > :e8080000         ady  #,b
> > :43020000 moveup: lda  ,-x
> > :a3040000         sta  ,-y
> > :8c09fffd         dbn  moveup,b
> > :5e0c0000         rts
> > [/code]
> > 
> > Mike B.
> 
> I think so, yes.
> 
> I just knocked this up to move blocks around. It's for my hobby Forth
> system running on antiquated (>30 years old) hardware. Think 5.25" 
> floppies and you're in the ball park.
> 
> It uses locals. From some quick experiments, locals on a dumb (non-
> optimising) ITC makes things faster. The reason? All the stack juggling
> goes away. Those ROTs DUPs SWAPs etc are burning up time just getting 
> the stack arranged. Locals on a dumb system takes that away. The
> argument doesn't hold on modern optimising systems.
> 
> Anyway, it's moot... The disk I/O is millions of times slower than
> the code! But locals sure makes it easy... Like falling of a log.
> 
> Ignore FLUSH? It just checks the block buffers and one or more is
> not flushed (dirty?) it offers the choice to do a flush first.
> 
> : movblk ( src dest cnt -- )
>   locals{ src dest cnt cpydir }
>   set cnt   set dest   set src 
>   src dest < if
>     cnt 1- +set src
>     cnt 1- +set dest
>     -1 set cpydir 
>   else
>     1 set cpydir
>   then flush? 
>   cnt 0 do
>     2 spaces src . ." to " dest .
>     src block drop  0 dest setblk  0 dirty flush
>     cpydir +set src   
>     cpydir +set dest
>   loop ;

Woops....

37 CLOAD LOCALS{
: flush? ( -- ) \ offer choice to flush if buffers are dirty 
  0  #buf @ 0 do i dirty? or loop if ." Flush? (Y/N)" key dup 
  ascii Y = swap ascii y = or if flush then then empty-buffers ;
  
: movblk ( src dest cnt -- )
  locals{ src dest cnt cpydir }
  set cnt   set dest   set src 
  src dest < if
    cnt 1- +set src
    cnt 1- +set dest
    -1 set cpydir 
  else
    1 set cpydir
  then flush? 
  cnt 0 do
    2 spaces src . ." to " dest .
    src block drop  0 dest setblk  0 dirty flush
    cpydir +set src   
    cpydir +set dest
  loop ;

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


#41401

From"HAA" <someone@microsoft.com>
Date2015-08-20 04:39 +1000
Message-ID<mr2ifi$53m$1@speranza.aioe.org>
In reply to#41382
Mark Wills wrote:
> >
> > I just knocked this up to move blocks around. It's for my hobby Forth
> > system running on antiquated (>30 years old) hardware. Think 5.25"
> > floppies and you're in the ball park.
> >
> > It uses locals. From some quick experiments, locals on a dumb (non-
> > optimising) ITC makes things faster. The reason? All the stack juggling
> > goes away. Those ROTs DUPs SWAPs etc are burning up time just getting
> > the stack arranged. Locals on a dumb system takes that away. The
> > argument doesn't hold on modern optimising systems.
> >
> > Anyway, it's moot... The disk I/O is millions of times slower than
> > the code! But locals sure makes it easy... Like falling of a log.
> > ...
>
> 37 CLOAD LOCALS{
> : flush? ( -- ) \ offer choice to flush if buffers are dirty
>   0  #buf @ 0 do i dirty? or loop if ." Flush? (Y/N)" key dup
>   ascii Y = swap ascii y = or if flush then then empty-buffers ;
>
> : movblk ( src dest cnt -- )
>   locals{ src dest cnt cpydir }
>   set cnt   set dest   set src
>   src dest < if
>     cnt 1- +set src
>     cnt 1- +set dest
>     -1 set cpydir
>   else
>     1 set cpydir
>   then flush?
>   cnt 0 do
>     2 spaces src . ." to " dest .
>     src block drop  0 dest setblk  0 dirty flush
>     cpydir +set src
>     cpydir +set dest
>   loop ;

Too many variables.

: bcopy ( src dest -- )
   cr ." Copy " swap u. ." to " u.
\   swap block swap buffer 1024 cmove
\   update save-buffers
;

: movblk ( src dest cnt -- )
   ?dup if
      swap  2 pick - >r  1- over +
      r@ 0< if  1+ swap  1 else -1 then
      r> 2swap do  i 2dup + bcopy  over +loop
   then 2drop ;

10 12 bcopy
Copy 10 to 12  ok

10 12 5 movblk
Copy 14 to 16
Copy 13 to 15
Copy 12 to 14
Copy 11 to 13
Copy 10 to 12  ok

12 10 5 movblk
Copy 12 to 10
Copy 13 to 11
Copy 14 to 12
Copy 15 to 13
Copy 16 to 14  ok


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


#41402

From"Elizabeth D. Rather" <erather@forth.com>
Date2015-08-19 09:15 -1000
Message-ID<A9SdnbJokKR_SEnInZ2dnUU7-VednZ2d@supernews.com>
In reply to#41381
On 8/18/15 8:35 AM, Mark Wills wrote:
> On Tuesday, 18 August 2015 18:10:22 UTC+1, Michael Barry  wrote:
>> On Tuesday, August 18, 2015 at 9:59:02 AM UTC-7, Mark Wills wrote:
>>>
>>>> : move ( from to count -- )
>>>>    >r 2dup u< if
>>>>      r> cmove>
>>>>    else
>>>>      r> cmove
>>>>    then ;
>>>>
>>>> Better branch prediction accuracy:
>>>>
>>>> : move ( from to count -- )
>>>>    >r 2dup dup r@ + within if
>>>>      r> cmove
>>>>    else
>>>>      r> cmove>
>>>>    then ;
>>>>
>>>> Both not tested.
>>>>
>>>> - anton
>>>> --
>>>>
>>>
>>> That's nice code, thank you. Mine also included WITHIN but your first
>>> example is neater IMO. I just tested it quickly and it seems to work fine.
>>>
>>> Thanks.
>>>
>>> Mark
>>
>> Isn't it true that the decision can be made based simply on whether source start is less than destination start, regardless of count?  Mine does that, but CMOVE> and CMOVE have equivalent performance, which might mot always be the case.
>>
>> [code]
>>
>> ;----------- 65m32: smart move --------
>> ; Move memory up/down (1 W to 4 GW)
>> ; x = source start address
>> ; y = destination start address
>> ; b = number of words to move
>> ; (4 GW are moved if b == 0 !!)
>> ;
>> :88020000 move:   cpy  #,x
>> :42420000 mvdown: lda  [cc],x+
>> :a2440000         sta  [cc],y+
>> :8c49fffd         dbn  [cc]mvdown,b
>> :5e4c0000         rts  [cc]
>> :e4080000         adx  #,b
>> :e8080000         ady  #,b
>> :43020000 moveup: lda  ,-x
>> :a3040000         sta  ,-y
>> :8c09fffd         dbn  moveup,b
>> :5e0c0000         rts
>> [/code]
>>
>> Mike B.
>
> I think so, yes.
>
> I just knocked this up to move blocks around. It's for my hobby Forth
> system running on antiquated (>30 years old) hardware. Think 5.25"
> floppies and you're in the ball park.
>
> It uses locals. From some quick experiments, locals on a dumb (non-
> optimising) ITC makes things faster. The reason? All the stack juggling
> goes away. Those ROTs DUPs SWAPs etc are burning up time just getting
> the stack arranged. Locals on a dumb system takes that away. The
> argument doesn't hold on modern optimising systems.
>
> Anyway, it's moot... The disk I/O is millions of times slower than
> the code! But locals sure makes it easy... Like falling of a log.
>
> Ignore FLUSH? It just checks the block buffers and one or more is
> not flushed (dirty?) it offers the choice to do a flush first.
>
> : movblk ( src dest cnt -- )
>    locals{ src dest cnt cpydir }
>    set cnt   set dest   set src
>    src dest < if
>      cnt 1- +set src
>      cnt 1- +set dest
>      -1 set cpydir
>    else
>      1 set cpydir
>    then flush?
>    cnt 0 do
>      2 spaces src . ." to " dest .
>      src block drop  0 dest setblk  0 dirty flush
>      cpydir +set src
>      cpydir +set dest
>    loop ;
>

The code with locals looks to me a lot messier than the earlier example. 
In any case, a traditional block move would be quite simple:

: BMOVE (n1 n2 -- ) \ Moves the content of block n1 to n2.
    >R BLOCK R> BLOCK 1024 CMOVE  UPDATE ;

Very simple; locals would not be helpful. When BLOCK gets a buffer for a 
block not already in memory, it will automatically write it to disk if 
the selected buffer's contents are marked as UPDATED, so that's not 
something the MOVE word needs to know about. Further, you know you can 
count on there not being any overlap. If you have a version of MOVE that 
does cell-wise moves, as Anton points out, that's preferable to CMOVE in 
this case.

Cheers,
Elizabeth

-- 
==================================================
Elizabeth D. Rather   (US & Canada)   800-55-FORTH
FORTH Inc.                         +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

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


#41592

From"HAA" <someone@microsoft.com>
Date2015-08-28 22:39 +1000
Message-ID<mrpknd$37p$1@speranza.aioe.org>
In reply to#41381
Mark Wills wrote:
>
> It uses locals. From some quick experiments, locals on a dumb (non-
> optimising) ITC makes things faster. The reason? All the stack juggling
> goes away. Those ROTs DUPs SWAPs etc are burning up time just getting
> the stack arranged. Locals on a dumb system takes that away. The
> argument doesn't hold on modern optimising systems.

I implemented TurboForth locals for LMI PC/Forth 3.2 (8086 ITC)
and ran a benchmark based on MOVBLK with and without locals.
A Pentium PC was used for the test.

Speed (I/O and CMOVE code replaced with 2DROP)

    locals            without locals
    63 sec          52 sec

Code size (less headers)

    locals            without locals
    122 bytes      92  bytes

Using an 8086 DTC forth

    locals            without locals
    21 sec          9 sec

The benchmark used for the test is shown below.  I'll post the source for
the LMI TurboForth locals if anyone wants it and you have no objection.
Your website doesn't mention whether derivative works are permitted.

   13
 0 \ TEST2
 1
 2 : bcopy ( src dest -- )
 3 \  CR ." Copy " SWAP U. ." to " U.
 4   SWAP BLOCK SWAP BUFFER 1024 CMOVE  UPDATE FLUSH
 5 ;
 6 : movblk1 ( src dest cnt -- )
 7   ?DUP IF
 8     SWAP  2 PICK - >R  OVER +
 9     R@ 0< IF  SWAP 1  ELSE  1- -1 THEN
10     R> 2SWAP DO  I 2DUP + 2DROP ( bcopy)  OVER +LOOP
11   THEN 2DROP ;
12
13
14
15

   14
 0 \ TEST2
 1
 2 : movblk2 ( src dest cnt -- )
 3   LOCALS{ src dest cnt cpydir }
 4   SET cnt   SET dest   SET src
 5   1 SET cpydir  src dest < IF
 6     cnt 1- +SET src    cnt 1- +SET dest    -1 SET cpydir
 7   THEN  ( flush? )  cnt 0 ?DO
 8 \    2 SPACES src . ." to " dest .
 9 \    src block drop  0 dest setblk  0 dirty flush
10 \    src BLOCK  dest BUFFER  1024 CMOVE  UPDATE  FLUSH
11  src dest 2DROP
12     cpydir +SET src  cpydir +SET dest
13   LOOP ;
14
15

   15
 0 \ TEST2
 1 : T1  7 EMIT  20 0 DO
 2     0 0 DO  10 12 5 movblk1  12 10 5 movblk1  LOOP
 3   LOOP  7 EMIT ;
 4
 5 : T2  7 EMIT  20 0 DO
 6     0 0 DO  10 12 5 movblk2  12 10 5 movblk2  LOOP
 7   LOOP  7 EMIT ;
 8
 9
10
11
12
13
14
15


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


#41594

FromCoos Haak <chforth@hccnet.nl>
Date2015-08-28 15:06 +0200
Message-ID<17n3lioulkme0$.1sc8iaelhms65$.dlg@40tude.net>
In reply to#41592
Op Fri, 28 Aug 2015 22:39:42 +1000 schreef HAA:

> Mark Wills wrote:
>>
>> It uses locals. From some quick experiments, locals on a dumb (non-
>> optimising) ITC makes things faster. The reason? All the stack juggling
>> goes away. Those ROTs DUPs SWAPs etc are burning up time just getting
>> the stack arranged. Locals on a dumb system takes that away. The
>> argument doesn't hold on modern optimising systems.
> 
> I implemented TurboForth locals for LMI PC/Forth 3.2 (8086 ITC)
> and ran a benchmark based on MOVBLK with and without locals.
> A Pentium PC was used for the test.
> 
> Speed (I/O and CMOVE code replaced with 2DROP)
> 
>     locals            without locals
>     63 sec          52 sec
> 
> Code size (less headers)
> 
>     locals            without locals
>     122 bytes      92  bytes
> 
> Using an 8086 DTC forth
> 
>     locals            without locals
>     21 sec          9 sec
> 
> The benchmark used for the test is shown below.  I'll post the source for
> the LMI TurboForth locals if anyone wants it and you have no objection.
> Your website doesn't mention whether derivative works are permitted.
> 
>    13
>  0 \ TEST2
>  1
>  2 : bcopy ( src dest -- )
>  3 \  CR ." Copy " SWAP U. ." to " U.
>  4   SWAP BLOCK SWAP BUFFER 1024 CMOVE  UPDATE FLUSH
>  5 ;
>  6 : movblk1 ( src dest cnt -- )
>  7   ?DUP IF
>  8     SWAP  2 PICK - >R  OVER +
>  9     R@ 0< IF  SWAP 1  ELSE  1- -1 THEN
> 10     R> 2SWAP DO  I 2DUP + 2DROP ( bcopy)  OVER +LOOP
> 11   THEN 2DROP ;
> 12
> 13
> 14
> 15
> 
>    14
>  0 \ TEST2
>  1
>  2 : movblk2 ( src dest cnt -- )
>  3   LOCALS{ src dest cnt cpydir }
>  4   SET cnt   SET dest   SET src
>  5   1 SET cpydir  src dest < IF
>  6     cnt 1- +SET src    cnt 1- +SET dest    -1 SET cpydir
>  7   THEN  ( flush? )  cnt 0 ?DO
>  8 \    2 SPACES src . ." to " dest .
>  9 \    src block drop  0 dest setblk  0 dirty flush
> 10 \    src BLOCK  dest BUFFER  1024 CMOVE  UPDATE  FLUSH
> 11  src dest 2DROP
> 12     cpydir +SET src  cpydir +SET dest
> 13   LOOP ;
> 14
> 15
> 
>    15
>  0 \ TEST2
>  1 : T1  7 EMIT  20 0 DO
>  2     0 0 DO  10 12 5 movblk1  12 10 5 movblk1  LOOP
>  3   LOOP  7 EMIT ;
>  4
>  5 : T2  7 EMIT  20 0 DO
>  6     0 0 DO  10 12 5 movblk2  12 10 5 movblk2  LOOP
>  7   LOOP  7 EMIT ;
>  8
>  9
> 10
> 11
> 12
> 13
> 14
> 15

Why the FLUSH? BUFFER knows when to write an UPDATEd blockbuffer.

groet Coos

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


#41602

From"HAA" <someone@microsoft.com>
Date2015-08-29 17:15 +1000
Message-ID<mrrmin$kct$1@speranza.aioe.org>
In reply to#41594
Coos Haak wrote:
>
> Why the FLUSH? BUFFER knows when to write an UPDATEd blockbuffer.
>
> groet Coos

BUFFER won't FLUSH the last block.


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


#41605

FromCoos Haak <chforth@hccnet.nl>
Date2015-08-29 13:24 +0200
Message-ID<yk9m84rtqpwe.1recy578ttef0$.dlg@40tude.net>
In reply to#41602
Op Sat, 29 Aug 2015 17:15:27 +1000 schreef HAA:

> Coos Haak wrote:
>>
>> Why the FLUSH? BUFFER knows when to write an UPDATEd blockbuffer.
>>
>> groet Coos
> 
> BUFFER won't FLUSH the last block.

Admitted, but once is enough.

groet Coos

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


#41618

From"HAA" <someone@microsoft.com>
Date2015-08-31 11:38 +1000
Message-ID<ms0b2s$m6$1@speranza.aioe.org>
In reply to#41605
Coos Haak wrote:
> Op Sat, 29 Aug 2015 17:15:27 +1000 schreef HAA:
>
> > Coos Haak wrote:
> >>
> >> Why the FLUSH? BUFFER knows when to write an UPDATEd blockbuffer.
> >>
> >> groet Coos
> >
> > BUFFER won't FLUSH the last block.
>
> Admitted, but once is enough.
>
> groet Coos

For this application there is little to be gained putting FLUSH outside the loop.




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


#41607

From"Elizabeth D. Rather" <erather@forth.com>
Date2015-08-29 07:59 -1000
Message-ID<3LKdncZ6heGDbnzInZ2dnUU7-QGdnZ2d@supernews.com>
In reply to#41602
On 8/28/15 9:15 PM, HAA wrote:
> Coos Haak wrote:
>>
>> Why the FLUSH? BUFFER knows when to write an UPDATEd blockbuffer.
>>
>> groet Coos
>
> BUFFER won't FLUSH the last block.

BUFFER should write the content of any block that has been marked 
UPDATEd before reusing that buffer. You really only need to FLUSH when 
you're about to shut down the computer.

Cheers,
Elizabeth

-- 
==================================================
Elizabeth D. Rather   (US & Canada)   800-55-FORTH
FORTH Inc.                         +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

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


Page 1 of 2  [1] 2  Next page →

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


csiph-web