Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #44782 > unrolled thread
| Started by | Chris Curl <ccurl609@gmail.com> |
|---|---|
| First post | 2016-01-12 07:47 -0800 |
| Last post | 2016-02-11 07:39 -0800 |
| Articles | 20 on this page of 127 — 28 participants |
Back to article view | Back to comp.lang.forth
Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 07:47 -0800
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-12 16:25 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-12 10:45 -0600
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 08:46 -0800
Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 11:57 -0500
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 09:22 -0800
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-12 21:04 -0800
Re: Ruby/Forth challenge for WJ Ron Aaron <rambamist@gmail.com> - 2016-01-13 07:59 +0200
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-12 19:42 +0000
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 12:53 -0800
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-13 15:45 +0000
Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-13 13:44 -0500
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 11:39 -0800
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-14 05:01 +0100
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 12:28 +0000
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 09:50 -0800
Re: Ruby/Forth challenge for WJ Pablo Hugo Reda <pabloreda@gmail.com> - 2016-01-12 11:50 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 12:30 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 12:43 -0800
Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-12 21:01 +0000
Re: Ruby/Forth challenge for WJ peter.m.falth@gmail.com - 2016-01-12 15:00 -0800
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 16:13 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-12 16:22 -0800
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 16:24 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-12 17:46 -0800
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 18:39 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-13 13:05 -0800
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-14 04:33 +0100
Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-14 03:27 -0800
Re: Ruby/Forth challenge for WJ peter.m.falth@gmail.com - 2016-01-14 04:42 -0800
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 13:03 +0000
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 21:17 -0800
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-13 21:44 -0800
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-14 10:57 +0000
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 12:20 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 13:57 -0800
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-14 14:22 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-14 16:14 -0800
Re: Ruby/Forth challenge for WJ Melzzzzz <mel@zzzzz.com> - 2016-01-15 03:05 +0100
Re: Ruby/Forth challenge for WJ Waldek Hebisch <hebisch@antispam.uni.wroc.pl> - 2016-01-15 00:41 +0000
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-15 16:22 +0000
Re: Ruby/Forth challenge for WJ mhx@iae.nl (Marcel Hendrix) - 2016-01-16 11:44 +0200
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-16 04:49 -0800
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-16 15:05 +0000
Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-18 03:26 -0800
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-18 12:48 +0000
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-19 22:26 +0100
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-20 03:05 -0800
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-20 21:00 +0100
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-20 15:57 -0800
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-21 23:02 +0100
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-22 01:25 +0000
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-21 18:05 -0800
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-21 22:03 -0800
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-20 13:40 +0000
Re: Ruby/Forth challenge for WJ m.a.m.hendrix@tue.nl - 2016-01-18 03:55 -0800
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-23 15:13 -0600
Re: Ruby/Forth challenge for WJ mhx@iae.nl - 2016-01-24 00:55 -0800
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 04:48 -0600
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-25 12:39 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 08:05 -0600
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-25 16:40 +0000
Re: Ruby/Forth challenge for WJ Mark Wills <markwills1970@gmail.com> - 2016-01-25 04:44 -0800
Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-25 14:01 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 08:08 -0600
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-25 11:56 -0600
Re: Ruby/Forth challenge for WJ "Elizabeth D. Rather" <erather@forth.com> - 2016-01-25 11:12 -1000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 03:33 -0600
Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 11:09 +0000
Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 11:06 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 07:45 -0600
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-26 16:46 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-26 11:16 -0600
Object-oriented Forth (was: Ruby/Forth challenge for WJ) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-27 14:13 +0000
Re: Object-oriented Forth Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-27 10:33 -0600
Re: Object-oriented Forth hughaguilar96@gmail.com - 2016-01-27 08:45 -0800
Re: Object-oriented Forth Chris Curl <ccurl609@gmail.com> - 2016-01-27 09:14 -0800
Re: Object-oriented Forth hughaguilar96@gmail.com - 2016-01-29 21:57 -0800
Re: Object-oriented Forth Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-30 10:58 +0000
Re: Object-oriented Forth Chris Curl <ccurl609@gmail.com> - 2016-01-30 09:38 -0800
Re: Object-oriented Forth Coos Haak <chforth@hccnet.nl> - 2016-01-30 20:39 +0100
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-26 15:56 +0100
Re: Ruby/Forth challenge for WJ stephen@mpeforth.com (Stephen Pelc) - 2016-01-26 20:46 +0000
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-25 22:27 +0100
Re: Ruby/Forth challenge for WJ Roelf Toxopeus <rt4all@notthis.hetnet.nl> - 2016-01-28 14:20 +0100
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 08:06 -0600
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-28 16:14 +0100
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 10:32 -0600
Re: Ruby/Forth challenge for WJ anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-01-28 17:26 +0000
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-28 12:13 -0600
Re: Ruby/Forth challenge for WJ Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-01-29 11:07 +0000
Re: Ruby/Forth challenge for WJ Bernd Paysan <bernd.paysan@gmx.de> - 2016-01-29 21:18 +0100
Re: Ruby/Forth challenge for WJ Tessa Bonting <tessa.bonting@gmail.com> - 2016-01-16 06:24 -0800
Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:21 -0500
Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:36 -0500
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 10:33 -0800
Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-14 01:37 -0500
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 13:45 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 13:55 -0800
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-12 14:34 -0800
Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 19:00 -0500
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 16:49 -0800
Re: Ruby/Forth challenge for WJ rickman <gnuarm@gmail.com> - 2016-01-12 22:18 -0500
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-01-12 14:31 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-12 16:05 -0800
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-01-13 07:58 +0000
Re: Ruby/Forth challenge for WJ Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-01-13 05:17 -0500
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-13 12:36 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-13 12:53 -0800
Re: Ruby/Forth challenge for WJ Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-01-14 06:50 -0600
Re: Ruby/Forth challenge for WJ Julian Fondren <julian.fondren@gmail.com> - 2016-01-13 05:36 -0800
Re: Ruby/Forth challenge for WJ lehs <skydda.barnen@gmail.com> - 2016-01-13 11:59 -0800
Re: Ruby/Forth challenge for WJ Chris Curl <ccurl609@gmail.com> - 2016-01-21 21:08 -0800
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:36 +0000
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:48 +0000
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-02-09 12:02 -0800
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 13:58 +0000
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-09 14:30 +0000
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-14 15:35 +0000
Re: Ruby/Forth challenge for WJ franck.bensusan@gmail.com - 2016-02-14 08:50 -0800
Re: Ruby/Forth challenge for WJ Julian Fondren <julian.fondren@gmail.com> - 2016-02-14 20:09 -0800
Re: Ruby/Forth challenge for WJ hughaguilar96@gmail.com - 2016-02-15 08:52 -0800
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-02-14 21:31 +0000
Re: Ruby/Forth challenge for WJ "WJ" <w_a_x_man@yahoo.com> - 2016-01-14 22:49 +0000
Re: Ruby/Forth challenge for WJ Paul Rubin <no.email@nospam.invalid> - 2016-01-14 15:31 -0800
Re: Ruby/Forth challenge for WJ Melzzzzz <mel@zzzzz.com> - 2016-01-15 06:55 +0100
Re: Ruby/Forth challenge for WJ djc <ciesinger@gmx.net> - 2016-02-11 07:39 -0800
Page 5 of 7 — ← Prev page 1 2 3 4 [5] 6 7 Next page →
| From | Coos Haak <chforth@hccnet.nl> |
|---|---|
| Date | 2016-01-30 20:39 +0100 |
| Subject | Re: Object-oriented Forth |
| Message-ID | <fo3dorfgplyv.1j1wm8841cufh$.dlg@40tude.net> |
| In reply to | #45203 |
Op Sat, 30 Jan 2016 09:38:32 -0800 (PST) schreef Chris Curl: <snip> > Thanks. I might be missing something though, because it seems to me that in Forth, > assuming you are using a stack (either the main stack or an auxiliary stack) for > local variables, this ability is built in, simply because the calling word's local > variables are on the stack when the child word is called. The called word just needs > to know where to look. If "quotations" is just a way to refer to such an approach, > then I think I get it. Locals cannot be on the data stack, what will happen someone used SWAP ? Locals must be on the return stack or a dedicatet locals stack. groet Coos
[toc] | [prev] | [next] | [standalone]
| From | Bernd Paysan <bernd.paysan@gmx.de> |
|---|---|
| Date | 2016-01-26 15:56 +0100 |
| Message-ID | <n88198$dcg$1@dont-email.me> |
| In reply to | #45083 |
Stephen Pelc wrote: > And perhaps you would let those who want to standardise an > old-fashioned OOP do so in peace. The problem of the 20 years old Forth OOP extensions is that they have too little overlap in the features to be useful outside of the box they have been made for. These 20+ OOP systems are *not* the same, rather the contrarly: They explore all different parts of the OOP space, IIRC, we have found at least 6 orthogonal decisions, which means that there is room for 64 different and mutually incompatible OOP systems. The discussion with Klaus was very symptomatic with a lots of "I don't need this", just because he never had thought of this particular possible feature. This was a core concept of OOP according to the literature... Andrew's idea was to provide building blocks so that people can use those to create their special-purpose OOP system, or extend their special purpose OOP system by using those building blocks to make them more generalized. My experience with proposing such building blocks (like the current object + instance and method invocation based on it, or the recognizer) is that the "I don't need this" mentality is still very strong. Especially, since the strongest "I don't need this" came from exactly the person which needs it most, because he has cluttered his outer interpreter with tons of hooks, because he had needed recognizers 20 years ago, but didn't realize it. Forth design says you should only solve the problem at hand, and not overgeneralize. So "I don't need this" as answer is perfectly fine in the Forth world; the consequence however is that this particular aspect is not going to be standardized. So whoever calls for a standard on OOP shall stop telling other people that he doesn't need this or that, or shut up with his request for standardization. The second option is perfectly fine, we probably don't need an OOP standard. We too much strive for simplicity and lightweight solutions that are only fit for a particular purpose, but we then really should accept that they are of limited reusability, and therefore not good enough for everybody. -- Bernd Paysan "If you want it done right, you have to do it yourself" net2o ID: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ* http://bernd-paysan.de/
[toc] | [prev] | [next] | [standalone]
| From | stephen@mpeforth.com (Stephen Pelc) |
|---|---|
| Date | 2016-01-26 20:46 +0000 |
| Message-ID | <56a7da71.1184619893@news.eternal-september.org> |
| In reply to | #45088 |
On Tue, 26 Jan 2016 15:56:15 +0100, Bernd Paysan <bernd.paysan@gmx.de> wrote: >My experience with proposing such building blocks (like the current object + >instance and method invocation based on it, or the recognizer) is that the >"I don't need this" mentality is still very strong. Especially, since the >strongest "I don't need this" came from exactly the person which needs it >most, because he has cluttered his outer interpreter with tons of hooks, >because he had needed recognizers 20 years ago, but didn't realize it. You have not understood my objections to standardising recognisers *now*. Please let me speak for myself. 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 | Bernd Paysan <bernd.paysan@gmx.de> |
|---|---|
| Date | 2016-01-25 22:27 +0100 |
| Message-ID | <n863qn$7m4$1@dont-email.me> |
| In reply to | #45066 |
Stephen Pelc wrote:
> On Mon, 25 Jan 2016 04:48:12 -0600, Andrew Haley
> <andrew29@littlepinkcloud.invalid> wrote:
>
>>And a final conclusion: we still don't have any kind of standard
>>concurrency mechanisms in Forth. Sigh. Some kind of load-balancing
>>system like Cilk Plus would be a nice thing to have, and wouldn't be
>>all that hard to use.
>
> Well, propose a basic one for single CPU use. Then you can have EXT
> for multi-core. Hmm, you still still owe us the OOP proposal you
> made some years ago.
Gforth uses words derived from the "de facto standard" cooperative Forth
multitasker to define pthread-based multithreading, has semaphores to avoid
conflicts, and events for inter-task communication.
That's a level below Cilk Plus with spawn+sync, but you can easily define it
by creating a worker thread for every core you have, and then have the
following events:
--------------------------cilk.fs--------------------------
require unix/pthread.fs
s" grep siblings /proc/cpuinfo | head -1 | cut -f2 -d:" r/o open-pipe throw
include-file Value cores
Variable sync#
Variable workers
User invoker
: worker@ ( -- worker )
BEGIN workers $@ IF @ workers 0 cell $del ELSE drop 0 THEN
dup 0= WHILE drop stop REPEAT ;
event: ->sync ( task -- )
{ w^ task } task cell workers $+! -1 sync# +! ;
: +worker ( task -- )
<event up@ elit, ->sync event> ;
event: ->spawn ( xt task -- )
invoker ! execute clearstack ;
: worker-thread ( -- )
stacksize4 newtask4 activate [ up@ ]l invoker !
BEGIN invoker @ +worker stop AGAIN ;
cores 1 max 0 [DO] worker-thread [LOOP] 1 ms sync# off
: sync ( -- )
\G wait for all spawned tasks to complete
BEGIN sync# @ 0> WHILE stop REPEAT ;
: spawn-rest ( xt -- )
elit, up@ elit, ->spawn worker@ event> 1 sync# +! ;
: spawn ( xt -- )
\G wait for a worker to become free, and spawn xt there
<event spawn-rest ;
: spawn1 ( n xt -- )
\G wait for a worker to become free, and spawn xt there, with one
argument
<event swap elit, spawn-rest ;
: spawn2 ( n1 n2 xt -- )
\G wait for a worker to become free, and spawn xt there, with two
arguments
<event >r swap elit, elit, r> spawn-rest ;
0 warnings !@
: bye ( -- )
sync cores 0 ?DO worker@ kill LOOP 1 ms bye ;
warnings !
--------------------------cilk.fs--------------------------
with WORKER@ choosing the next free worker (if any); blocking if none is
ready (it will be woken up by the next ->sync event).
STOP contains the event interpreter, which is essentially a token-threaded
Forth for all those words defined by event:.
Assumption: Main thread spawns and syncs, helper thread just perform
workload; therefore sync# doesn't need to be a user variable, and workers
doesn't need a semaphore to protect it.
The single-thread implementation is trivial:
: sync ( -- ) ;
: spawn ( xt -- ) execute ; \ spawn1 + 2 same definition
That was a remarkable quick exercise. Results probably should be returned
by storing them into a passed address. The event mechanism can be used to
pass arguments when spawning and return values at completion.
If you allow recursive spawning, sync should add the current thread as
worker, and remove it after sync is completed.
Test:
: test ( n -- ) ms ." test done" cr ; ok
: tests ( n -- ) 0 DO i 100 * ['] test spawn1 LOOP
sync ." sync done" ;
16 tests
I'll probably experiment with this a bit more; it looks like spawn should be
separated in a pass-argument part, and what's now called spawn-rest.
--
Bernd Paysan
"If you want it done right, you have to do it yourself"
net2o ID: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ*
http://bernd-paysan.de/
[toc] | [prev] | [next] | [standalone]
| From | Roelf Toxopeus <rt4all@notthis.hetnet.nl> |
|---|---|
| Date | 2016-01-28 14:20 +0100 |
| Message-ID | <56aa15af$0$12326$e4fe514c@textnews.kpn.nl> |
| In reply to | #45077 |
On 25/01/16 22:27, Bernd Paysan wrote:
> Stephen Pelc wrote:
>
>> On Mon, 25 Jan 2016 04:48:12 -0600, Andrew Haley
>> <andrew29@littlepinkcloud.invalid> wrote:
>>
>>> And a final conclusion: we still don't have any kind of standard
>>> concurrency mechanisms in Forth. Sigh. Some kind of load-balancing
>>> system like Cilk Plus would be a nice thing to have, and wouldn't be
>>> all that hard to use.
>>
>> Well, propose a basic one for single CPU use. Then you can have EXT
>> for multi-core. Hmm, you still still owe us the OOP proposal you
>> made some years ago.
>
> Gforth uses words derived from the "de facto standard" cooperative Forth
> multitasker to define pthread-based multithreading, has semaphores to avoid
> conflicts, and events for inter-task communication.
>
> That's a level below Cilk Plus with spawn+sync, but you can easily define it
> by creating a worker thread for every core you have, and then have the
> following events:
>
> --------------------------cilk.fs--------------------------
> require unix/pthread.fs
>
> s" grep siblings /proc/cpuinfo | head -1 | cut -f2 -d:" r/o open-pipe throw
> include-file Value cores
>
> Variable sync#
> Variable workers
> User invoker
>
> : worker@ ( -- worker )
> BEGIN workers $@ IF @ workers 0 cell $del ELSE drop 0 THEN
> dup 0= WHILE drop stop REPEAT ;
>
> event: ->sync ( task -- )
> { w^ task } task cell workers $+! -1 sync# +! ;
> : +worker ( task -- )
> <event up@ elit, ->sync event> ;
>
> event: ->spawn ( xt task -- )
> invoker ! execute clearstack ;
> : worker-thread ( -- )
> stacksize4 newtask4 activate [ up@ ]l invoker !
> BEGIN invoker @ +worker stop AGAIN ;
>
> cores 1 max 0 [DO] worker-thread [LOOP] 1 ms sync# off
>
> : sync ( -- )
> \G wait for all spawned tasks to complete
> BEGIN sync# @ 0> WHILE stop REPEAT ;
> : spawn-rest ( xt -- )
> elit, up@ elit, ->spawn worker@ event> 1 sync# +! ;
> : spawn ( xt -- )
> \G wait for a worker to become free, and spawn xt there
> <event spawn-rest ;
> : spawn1 ( n xt -- )
> \G wait for a worker to become free, and spawn xt there, with one
> argument
> <event swap elit, spawn-rest ;
> : spawn2 ( n1 n2 xt -- )
> \G wait for a worker to become free, and spawn xt there, with two
> arguments
> <event >r swap elit, elit, r> spawn-rest ;
>
> 0 warnings !@
> : bye ( -- )
> sync cores 0 ?DO worker@ kill LOOP 1 ms bye ;
> warnings !
> --------------------------cilk.fs--------------------------
>
> with WORKER@ choosing the next free worker (if any); blocking if none is
> ready (it will be woken up by the next ->sync event).
>
> STOP contains the event interpreter, which is essentially a token-threaded
> Forth for all those words defined by event:.
>
> Assumption: Main thread spawns and syncs, helper thread just perform
> workload; therefore sync# doesn't need to be a user variable, and workers
> doesn't need a semaphore to protect it.
>
> The single-thread implementation is trivial:
>
> : sync ( -- ) ;
> : spawn ( xt -- ) execute ; \ spawn1 + 2 same definition
>
> That was a remarkable quick exercise. Results probably should be returned
> by storing them into a passed address. The event mechanism can be used to
> pass arguments when spawning and return values at completion.
>
> If you allow recursive spawning, sync should add the current thread as
> worker, and remove it after sync is completed.
>
> Test:
>
> : test ( n -- ) ms ." test done" cr ; ok
> : tests ( n -- ) 0 DO i 100 * ['] test spawn1 LOOP
> sync ." sync done" ;
> 16 tests
>
> I'll probably experiment with this a bit more; it looks like spawn should be
> separated in a pass-argument part, and what's now called spawn-rest.
>
Neat!
BTW I wonder if it occurred to you, or Andrew Haley for that matter,
that some Forth users already have a SPAWN in usage without any
knowledge of some existing non-Forth library.
For instance my current version of SPAWN is used for things like:
FRAMEWORK Carbon.framework
FUNCTION: SysBeep ( n -- ret )
: BEEP ( -- ) 0 SysBeep DROP ;
: BEEPER ( -- ) 20 CHOOSE 1+ 0 DO 180 800 ALEA MS BEEP LOOP ;
: BEEP+ ( -- ) 250 750 ALEA MS ['] BEEPER SPAWN ;
: BB ( -- ) BEGIN TOSS IF BEEP+ THEN KEY? UNTIL ;
Sonology way of testing random number generator(s) ;-)
I don't have SYNC and this version doesn't get a passed in parameter and
is not depending on the number of available cores.
There are a 1001 ways of doing this. Lots of variations. Depends on what
you need. I would always redefine SPAWN to the situation at hand.
It's such a useful name for many (similar) things.
As a non-english speaker, I first encountered the word and concept of
SPAWN in SuperCollider https://supercollider.github.io in the 1990's.
Found it a great catchy name to use in Forth for similar actions.
First implemented as anonymous, headless tasks (with garbage collector)
in MacForth's coop multitasker, on single core PPC. Later pthreads, then
threadpools with workers snoozing and lastly Grand Central Dispatch on
the Mac for SwiftForth, VFX and iForth, on multicore MacIntels.
To deliberately run a word on a separate core from the main thread, I
use the names FORK JOIN (and CONTINUE) as proposed by Andrew Haley a few
years ago. Similar to DFW's PAR END-PAR.
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2016-01-28 08:06 -0600 |
| Message-ID | <ENadncvB9K_WvTfLnZ2dnUU7-aOdnZ2d@supernews.com> |
| In reply to | #45077 |
Bernd Paysan <bernd.paysan@gmx.de> wrote: > > Assumption: Main thread spawns and syncs, helper thread just perform > workload; therefore sync# doesn't need to be a user variable, and workers > doesn't need a semaphore to protect it. > > The single-thread implementation is trivial: > > : sync ( -- ) ; > : spawn ( xt -- ) execute ; \ spawn1 + 2 same definition > > That was a remarkable quick exercise. Great, that's neat, but it's not work stealing. SYNC should only wait for a subset of tasks, not the ones spawned by other threads, and it's important not just to spin waiting for other threads if there is still work to be done. > I'll probably experiment with this a bit more; it looks like spawn > should be separated in a pass-argument part, and what's now called > spawn-rest. The real algorithm is more sophisticated than you're giving it credit for. It's described here: https://en.wikipedia.org/wiki/Work_stealing The lock-free algorithm for grabbing tasks to be done is very important to doing this efficiently. And it's very important to use a double-ended queue. Andrew.
[toc] | [prev] | [next] | [standalone]
| From | Bernd Paysan <bernd.paysan@gmx.de> |
|---|---|
| Date | 2016-01-28 16:14 +0100 |
| Message-ID | <n8db47$mr8$1@dont-email.me> |
| In reply to | #45153 |
Andrew Haley wrote: > Bernd Paysan <bernd.paysan@gmx.de> wrote: >> >> Assumption: Main thread spawns and syncs, helper thread just perform >> workload; therefore sync# doesn't need to be a user variable, and workers >> doesn't need a semaphore to protect it. >> >> The single-thread implementation is trivial: >> >> : sync ( -- ) ; >> : spawn ( xt -- ) execute ; \ spawn1 + 2 same definition >> >> That was a remarkable quick exercise. > > Great, that's neat, but it's not work stealing. SYNC should only wait > for a subset of tasks, not the ones spawned by other threads, and it's > important not just to spin waiting for other threads if there is still > work to be done. This first attempt works only for one spawner; I'm going to extend this. SYNC# will then become a user variable, so each thread is only counting the own spawns. >> I'll probably experiment with this a bit more; it looks like spawn >> should be separated in a pass-argument part, and what's now called >> spawn-rest. > > The real algorithm is more sophisticated than you're giving it credit > for. It's described here: > > https://en.wikipedia.org/wiki/Work_stealing > > The lock-free algorithm for grabbing tasks to be done is very > important to doing this efficiently. And it's very important to use a > double-ended queue. The IPC for the events (which need to be atomic) under Linux is so damn'd expensive (it needs to wake sleeping tasks, doing it generically costs about 10k instructions) that I need to look at doing that cheaper, too. As long as the task still is active, you don't have to wake it up, it will look into the event queue, anyways. -- Bernd Paysan "If you want it done right, you have to do it yourself" net2o ID: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ* http://bernd-paysan.de/
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2016-01-28 10:32 -0600 |
| Message-ID | <Ud6dnb6lA7kQ3zfLnZ2dnUU78IGdnZ2d@supernews.com> |
| In reply to | #45157 |
Bernd Paysan <bernd.paysan@gmx.de> wrote: > Andrew Haley wrote: > >> Bernd Paysan <bernd.paysan@gmx.de> wrote: >> >> https://en.wikipedia.org/wiki/Work_stealing >> >> The lock-free algorithm for grabbing tasks to be done is very >> important to doing this efficiently. And it's very important to use a >> double-ended queue. > > The IPC for the events (which need to be atomic) under Linux is so > damn'd expensive (it needs to wake sleeping tasks, doing it > generically costs about 10k instructions) that I need to look at > doing that cheaper, too. As long as the task still is active, you > don't have to wake it up, it will look into the event queue, > anyways. Indeed, and the queues (note that each worker has its own) have to be double-ended because local jobs are pulled from one end, and remote jobs from the other, balancing load and minimizing overhead. Andrew.
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2016-01-28 17:26 +0000 |
| Message-ID | <2016Jan28.182643@mips.complang.tuwien.ac.at> |
| In reply to | #45164 |
Andrew Haley <andrew29@littlepinkcloud.invalid> writes:
>Indeed, and the queues (note that each worker has its own) have to be
>double-ended because local jobs are pulled from one end, and remote
>jobs from the other, balancing load and minimizing overhead.
Not sure how that balances load more than taking the jobs from the
same end, but, concerning overhead, my guess is that this reduces
cache ping-ponging.
- 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.rigwit.co.uk/EuroForth2015/
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2016-01-28 12:13 -0600 |
| Message-ID | <CoudnSB-6vuxxzfLnZ2dnUU78L2dnZ2d@supernews.com> |
| In reply to | #45169 |
Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote: > Andrew Haley <andrew29@littlepinkcloud.invalid> writes: >>Indeed, and the queues (note that each worker has its own) have to be >>double-ended because local jobs are pulled from one end, and remote >>jobs from the other, balancing load and minimizing overhead. > > Not sure how that balances load more than taking the jobs from the > same end, but, concerning overhead, my guess is that this reduces > cache ping-ponging. Two things: except for the last item, a worker can pull and push tasks on its own queue with little or no synchronization. Remote workers must use a CAS. Also, small tasks are usually at the bottom end of the queue and large tasks are at the top, and remote workers prefer to steal large tasks. This minimizes communication overhead. But all of this is online, particularly [1] Andrew. [1] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf
[toc] | [prev] | [next] | [standalone]
| From | Albert van der Horst <albert@spenarnc.xs4all.nl> |
|---|---|
| Date | 2016-01-29 11:07 +0000 |
| Message-ID | <56ab47e4$0$23826$e4fe514c@news.xs4all.nl> |
| In reply to | #45157 |
Bernd Paysan <bernd.paysan@gmx.de> writes: >Andrew Haley wrote: >> Bernd Paysan <bernd.paysan@gmx.de> wrote: >>> >>> Assumption: Main thread spawns and syncs, helper thread just perform >>> workload; therefore sync# doesn't need to be a user variable, and workers >>> doesn't need a semaphore to protect it. >>> >>> The single-thread implementation is trivial: >>> >>> : sync ( -- ) ; >>> : spawn ( xt -- ) execute ; \ spawn1 + 2 same definition >>> >>> That was a remarkable quick exercise. >> >> Great, that's neat, but it's not work stealing. SYNC should only wait >> for a subset of tasks, not the ones spawned by other threads, and it's >> important not just to spin waiting for other threads if there is still >> work to be done. >This first attempt works only for one spawner; I'm going to extend this. >SYNC# will then become a user variable, so each thread is only counting the >own spawns. >>> I'll probably experiment with this a bit more; it looks like spawn >>> should be separated in a pass-argument part, and what's now called >>> spawn-rest. >> >> The real algorithm is more sophisticated than you're giving it credit >> for. It's described here: >> >> https://en.wikipedia.org/wiki/Work_stealing >> >> The lock-free algorithm for grabbing tasks to be done is very >> important to doing this efficiently. And it's very important to use a >> double-ended queue. >The IPC for the events (which need to be atomic) under Linux is so damn'd >expensive (it needs to wake sleeping tasks, doing it generically costs about >10k instructions) that I need to look at doing that cheaper, too. As long >as the task still is active, you don't have to wake it up, it will look into >the event queue, anyways. To be specific, if two task communicate through a classic pipe, a blocked read will set you back 10 K instructions? (That's not good for a parallel prime number sieve ;-) ) >-- >Bernd Paysan -- 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]
| From | Bernd Paysan <bernd.paysan@gmx.de> |
|---|---|
| Date | 2016-01-29 21:18 +0100 |
| Message-ID | <n8gh8o$o8p$1@dont-email.me> |
| In reply to | #45178 |
Albert van der Horst wrote: > To be specific, if two task communicate through a classic pipe, > a blocked read will set you back 10 K instructions? > (That's not good for a parallel prime number sieve ;-) ) Yes, any other IPC for waking up another core is about as expensive. A Core i7 with Linux is clearly not a GA144. -- Bernd Paysan "If you want it done right, you have to do it yourself" net2o ID: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ* http://bernd-paysan.de/
[toc] | [prev] | [next] | [standalone]
| From | Tessa Bonting <tessa.bonting@gmail.com> |
|---|---|
| Date | 2016-01-16 06:24 -0800 |
| Message-ID | <9943b371-987c-4115-bd11-791ba867d30b@googlegroups.com> |
| In reply to | #44905 |
Op zaterdag 16 januari 2016 11:45:00 UTC+1 schreef Marcel Hendrix: > anton@mips.complang.tuwien.ac.at (Anton Ertl) writes Re: Ruby/Forth challenge > \ FORTH> do-tests > \ count1 : 0.072 seconds elapsed. > \ count2 : 0.280 seconds elapsed. > \ count3 : 0.521 seconds elapsed. > \ count4 : 0.486 seconds elapsed. > \ count5 : 0.494 seconds elapsed. > \ count6 : 0.497 seconds elapsed. > \ count7 : 0.523 seconds elapsed. > \ count8a : 0.421 seconds elapsed. > \ count8b : 0.484 seconds elapsed. > \ count8c : 0.494 seconds elapsed. > \ count8d : 0.139 seconds elapsed. > \ count9 : 0.070 seconds elapsed. > \ count10 : 0.056 seconds elapsed. The branch prediction in a tide loop cost more cycles since the prediction is started with a paralel set of the registers and takes some cycles to see that it predicted it wright. Now in the tide loop a second prediction is started before the first is handled completely so a second set of the registers is used and the predicted jump is run. Now is it so that the pentium would only allow one prediction at a time, so there would be no difference between a tide or a large loop. From the pentium4 that changed since it introduced a jump prediction handling code buffer of about 8 jump long. So the jump prediction code buffer simply overflows as the result takes some time to chech that the pre- dection was right. As a result the next jump would have to wait for the buffer to have room for a start of a next code part to be handled and that gives a penalty of about 17 cycles. Newer precessor have a bigger prediction handling buffer but that also would overflow at some time. Putting extra instruction between the begin and the until fills the pipe lines (yes there are stil pipi lines and a lot of them) and gives the branch prediction the time to finish without the delays. Allso the out of order execution with the paralel execution of one 4 uops instruction with 3 1 uops instructions gives the somewhat stranch going faster as more NOP's are inserted, with the optimum of the time needed for the branch prediction cycles, and from there it just takes time to handle the extra NOP's.
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-01-13 05:21 -0500 |
| Message-ID | <20160113052158.07176e0d@_> |
| In reply to | #44808 |
On Tue, 12 Jan 2016 16:24:42 -0800
Paul Rubin <no.email@nospam.invalid> wrote:
> Paul Rubin <no.email@nospam.invalid> writes:
> >> with my 32 bit native code generating forth I get 983 ms on the
> >> same laptop
> > Interestingly, your 32 bit Forth is beating 64 bit C++ by a wide
> > margin, even with C++ running on a considerably faster machine
> > (i7-3770).
>
> Oh never mind, with optimization off and subscript checking on, I was
> getting about 1 sec (GCC 4.7.2). With optimization -O3 and unsafe
> subscripts, I get 141 ms. This is just for the counting part, not the
> random initialization, which depends considerably on which PRNG you
> use. The subscript checking actually only makes a tiny difference.
>
> ================================================================
>
> #include <iostream>
> #include <random>
> #include <array>
> #include <cstdint>
> #include <chrono>
>
> const int Bufsize = 1<<28;
> std::array<std::uint8_t, Bufsize+3> buf;
>
> void init_array()
> {
> std::minstd_rand rd;
> for (int i = 0; i < buf.size(); i += 3)
> {
> int r = rd();
> buf[i] = r&0xff;
> r >>= 8;
> buf[i+1] = r&0xff;
> r >>= 8;
> buf[i+2] = r&0xff;
> }
> }
>
> int main(int argc, char **argv) {
> auto t0 = std::chrono::high_resolution_clock::now();
> init_array();
> auto t1 = std::chrono::high_resolution_clock::now();
>
> static std::array<std::uint32_t, 256> counts;
> for (uint8_t b: buf) {
> ++counts[b];
> }
> auto t2 = std::chrono::high_resolution_clock::now();
> std::chrono::duration<double> d1 = t1 - t0;
> std::chrono::duration<double> d2 = t2 - t1;
> std::cout << d1.count () << " " << d2.count() << std::endl;
> return 0;
> }
Shouldn't r be unsigned?
Why didn't you use 'unsigned char' for buf?
I'm not familiar with C++, but I suspect 'i<buf.size()'
returns 'Bufsize+3'. Don't you want 'Bufsize' returned?
I used to use 'char **argv' instead of 'char *argv[]' for
many years also. It's not technically valid for C,
perhaps it is for C++. You didn't use them. So, 'void'.
Are the results of your app in seconds?
(g++ -std=c++11 -O2)
# ./pr
0.660104 0.436355
# ./pr
0.669993 0.436285
# ./pr
0.659609 0.43627
The results are going to be processor speed dependent.
If I attempt to convert your C++ code to ANSI C,
knowing very little about C++, the times come out
rather different:
# ./pr
1.016804 0.000000
# ./pr
0.926480 0.000000
# ./pr
1.002100 0.000000
All of the time is front loaded.
I would expect the times to be somewhat similar
but, I had to use one non-ANSI, Linux time function
which I've never used before.
I.e., if the counts aren't taking much time in C,
I'd wonder why C++ took so long. Or, why C++ was
so much faster with the array initialization than
C was.
Perhaps, I made a mistake porting somewhere. Or,
maybe there is some difference with the values
returned by the time functions? Maybe, -O2 optimized
away the unused counts loop for C, but kept it for
C++? Well, take a look or run it, if interested:
/* LINUX only, almost ANSI C */
/* for 32-bit or 64-bit */
#include <stdio.h> /* printf */
#include <stdlib.h> /* srand rand */
#include <time.h> /* time clock_gettime */
#define CNT 256
#define BUF 268435456UL
#define BIL 1000000000UL
unsigned char buf[BUF+3];
void init_array(void)
{
int i,r;
srand(time(0));
for(i=0;i<BUF;i+=3)
{
r=rand();
buf[i]=r&0xff;
r>>=8;
buf[i+1]=r&0xff;
r>>=8;
buf[i+2]=r&0xff;
}
}
int main(void)
{
unsigned int counts[CNT];
unsigned long i;
struct timespec tim0,tim1,tim2;
unsigned long long t0,t1,t2;
/* memset */
for(i=0;i<CNT;i++);
counts[i]=0;
clock_gettime(CLOCK_MONOTONIC,&tim0);
init_array();
clock_gettime(CLOCK_MONOTONIC,&tim1);
for(i=0;i<BUF;i++)
counts[buf[i]]++;
clock_gettime(CLOCK_MONOTONIC,&tim2);
t0=tim0.tv_sec*BIL+tim0.tv_nsec;
t1=tim1.tv_sec*BIL+tim1.tv_nsec;
t2=tim2.tv_sec*BIL+tim2.tv_nsec;
printf("%10.6f %10.6f\n",((double)(t1-t0))/BIL,((double)(t2-t1))/BIL);
return(0);
}
Rod Pemberton
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-01-13 05:36 -0500 |
| Message-ID | <20160113053654.65ba685a@_> |
| In reply to | #44819 |
On Wed, 13 Jan 2016 05:21:58 -0500 Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> wrote: > Why didn't you use 'unsigned char' for buf? Ignore that. It's a uint8_t. RP
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-01-13 10:33 -0800 |
| Message-ID | <8760yxuy6a.fsf@nightsong.com> |
| In reply to | #44819 |
Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> writes:
> Shouldn't r be unsigned?
Hmm, that would have been cleaner (actually uint_fast32_t) but int is ok
since the numbers from minstd_rand are always positive. Also I'm only
taking the lower 24 bits.
> I'm not familiar with C++, but I suspect 'i<buf.size()'
> returns 'Bufsize+3'. Don't you want 'Bufsize' returned?
Whoops! Nice catch. buf.size() was left over from a revision where I
was taking just 1 byte from each random number.
> I used to use 'char **argv' instead of 'char *argv[]' for
> many years also. It's not technically valid for C,
> perhaps it is for C++. You didn't use them. So, 'void'.
Per http://en.cppreference.com/w/cpp/language/main_function :
The names argc and argv are arbitrary, as well as the representation
of the types of the parameters: int main(int ac, char** av) is
equally valid.
Maybe I should check Stroustrup's book though.
> Are the results of your app in seconds?
> (g++ -std=c++11 -O2)
> # ./pr
> 0.660104 0.436355
I get: 0.382123 0.141022 (GCC 4.7.2 x86-64, i7-3770 3.4 GHz with -O2)
0.443481 0.140997 with -O3
This is with the Bufsize fix and also replaced buf[i] with buf.at(i)
etc. (That range-checks the subscript and causes almost no slowdown).
Interesting that -O3 does the initialization a little slower than -O2.
> # ./pr
> 1.016804 0.000000
The slower initialization is probably because minstd_rand is the C++
minimal standard RNG which is rather crappy but very fast. The C one is
probably slower. The 0.00000 is because the code is being optimized
away (see below).
> I.e., if the counts aren't taking much time in C
If it's really looking at 256M bytes then at 1 cycle per byte that's
around 0.1s at 2.5 GHz. I don't think it can do much better than that.
I put printf("%d\n", counts[23]) at the end of your C version, and that
gave:
0.673343 0.141221
it took 0.000000 without the extra print because the compiler saw that
counts (a local array in your version) was unused after being set. The
C++ version had counts as a global, so my guess is the compiler presumed
that some other module might use it.
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-01-14 01:37 -0500 |
| Message-ID | <20160114013746.71f8991c@_> |
| In reply to | #44831 |
On Wed, 13 Jan 2016 10:33:33 -0800
Paul Rubin <no.email@nospam.invalid> wrote:
> I put printf("%d\n", counts[23]) at the end of your C version, and
> that gave:
>
> 0.673343 0.141221
>
> it took 0.000000 without the extra print because the compiler saw that
> counts (a local array in your version) was unused after being set.
> The C++ version had counts as a global, so my guess is the compiler
> presumed that some other module might use it.
So, a few results without the optimized away loop:
1.006349 0.398377
1.035722 0.373584
1.026238 0.368511
0.964631 0.400756
Restructuring init_array() to not use shifts, but using
a pointer to char for direct byte reads, didn't seem to
help any. Results hovered around the same values.
Maybe, computing a long-term result would slightly favor
one method over the other. I didn't compare source via
gcc -S. One is likely to produce fewer instructions.
I also considered calling rand() more frequently to
eliminate shifts, but I didn't test that. I presumed
that rand() takes longer than the shifts.
FYI, those results are for:
3.2Ghz AMD Phenom II X2 555 (dual core)
64-bit VLocity Linux (VectorLinux)
GCC 4.7.2
Rod Pemberton
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-01-12 13:45 -0800 |
| Message-ID | <10f5274e-7f92-4ff1-a653-6d22fe076170@googlegroups.com> |
| In reply to | #44782 |
Update: about 890 MS on SP-Forth.
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-01-12 13:55 -0800 |
| Message-ID | <65ba1513-cfa4-4ebe-9583-4729f4b0815a@googlegroups.com> |
| In reply to | #44782 |
OK ... let's see how fast WJ's Ruby implementation runs. Since Ruby is so much better than the "toy" language Forth, Ruby can do the same thing be much faster than 600ms, right? WJ, the ball is in your court.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-01-12 14:34 -0800 |
| Message-ID | <87y4bumnpp.fsf@jester.gateway.pace.com> |
| In reply to | #44797 |
Chris Curl <ccurl609@gmail.com> writes:
> Since Ruby is so much better than the "toy" language Forth, Ruby can
> do the same thing be much faster than 600ms, right?
Just for laughs, I tried it in Python for 1MB instead of 256MB. The
random initialization phase took 0.743 sec and the counting phase took
0.009 sec, scaling to about 23 sec for counting 256MB. The random
initialization was pretty inefficient so I wouldn't count it despite not
seeing an obvious faster way. The counting phase was the quickest
obvious way I could think of offhand, though maybe there is something
better. The code is:
from random import randrange
import time
import array
import itertools
def main():
t0 = time.time()
vec = bytearray(itertools.islice(
iter(lambda: randrange(0,255), None),
2**20
)
)
t1 = time.time()
u = array.array('i',[0]*256)
for c in vec:
u[c] += 1
t2 = time.time()
print t1-t0, t2-t1
main()
[toc] | [prev] | [next] | [standalone]
Page 5 of 7 — ← Prev page 1 2 3 4 [5] 6 7 Next page →
Back to top | Article view | comp.lang.forth
csiph-web