Google Grupper støtter ikke lenger nye Usenet-innlegg eller -abonnementer. Historisk innhold er fortsatt synlig.

Short-circuiting user-defined operators

Sett 5 ganger
Hopp til første uleste melding

Austin Hastings

ulest,
3. apr. 2003, 17:36:1503.04.2003
til Hod...@writeme.com, perl6-l...@perl.org

--- Paul <ydb...@yahoo.com> wrote:
> > But what to do about matrix arithmetic and other simple threadable
> > tasks?
> >
> > sub m_add(@a, @b) {
> > my @result;
> > my $i, $j;
> > @result = @a;
> > for @result -> $i {:is threaded # Thread this block?
> > for @result[$i]; @b -> $j; $b {
> > $j += $b;
> > }
> > }
> > }
>
> isn't $i an element alias rather than an index there?

Yeah, but I'm assuming a 2d matrix. @result[$i] is another array.

> Basically, I just failed to parse all that. Sorry -- internal P6
> parser still incomplete.

No, just bad writing on my part. Sorry.

>
> > Conversely, I have absolutely no idea what to do about threading on
> a
> > per-data-object basis:
> >
> > sub m_add(@a is threaded, @b) {
> > ... What can the compiler figure out about threading @a?
> > }
>
> I'd say this is unlikely to work, but again, I haven't exactly
> thought it all through very thoroughly.

I'm pretty sure it *could* work. Likewise, I'm sure we could live
without this for the first release, if we but grab the namespace we
think we'll need in advance. That's why this stuff should all be hints
to the interpreter -- what the box is actually capable of is not
something we can know.

Certainly it's trivial to "thread" basic vector processing:

1. Get max# of useful threads (#cpu's - 1)?

2. Every computation of a threaded vector member gets allocated to
a new thread, round-robin.

3. Any read of a threaded vector member forces a join on the allocated
thread before proceeding.

This isn't optimal, but it would work. But knowing how much benefit
you're going to see will be part of the equation, too. So you want the
runtime to balance the startup/shutdown cost versus the execution cost,
if possible. Also, you want to favor threading when a blocking
operation might occur in the threadable code. That kind of stuff.

> > This is one of those cases where the really smart guys who used to
> > spend time recoding the fortran compilers for Vaxen might be able
> > clue us in on the "cool tricks for vector processing", but how
> > generalizable will it all be? (And, of course, is the internal
> > representation amenable to this?)
> > None of this addresses the issue of "explicit" threading -- cases
> > where the user wants to create and control her own threads.
>
> Or how they would interact. If you're doing implicit threading in a
> program using explicit threading, things could get REALLY
> tang-toungled....

Implicit threading must be transparent to the coder, or it's not
implicit, icit?

So if I have two explicit threads:

my ViewControlTask = new Task(...);
my ViewControlThread = new Thread(priority => 1,
task => ViewControlTask);

my ComputationTask = new Task(...);
my ComputationThread = new Thread(priority => 19,
task => ComputationTask);

Anything which happens *implicitly* in the ComputationTask must be
invisible to the coder. So the task will automatically be split and
automatically be joined (or not) based on the convenience of the
interpreter -- the only thing I'm doing in code is giving "hints" about
what can/should be split into threads.

So ideally, Parrot notices that I'm doing threads, or maybe that the
interpreter thinks that threads are going to be valuable. So it engages
the "threadomizer" and creates 8 OS level threads, one per CPU. Then
perl queries parrot, gets the number of threads created, and allocates
explicit threads and implicit threads accordingly -- this is what I
don't know how to do.

So there's a mixture:

ViewControlTask -----> -----> -----> --*--> -----> ----*> ----->
+ implicit thread 1 -----> -----/ \-----> --/

ComputationTask -----> -----> -----> -----> -----> * -----> ----->
+ implicit thread 1 -----> -----> -----> ---/
+ implicit thread 2 -----> -----> -----> ---/
+ implicit thread 3 -----> -----> -----> ---/
+ implicit thread 4 -----> -----> -----> ---/

=Austin

Larry Wall

ulest,
5. apr. 2003, 13:40:1205.04.2003
til perl6-l...@perl.org
On Tue, Apr 01, 2003 at 08:26:38PM -0500, Joe Gottman wrote:
: Is there any way to write a user-defined operator so that it
: short-circuits, like && and || ? This might be function trait, for
: instance,
:
: sub infix:!! ($lhs, $rhs) is short_circuit {...}

Honestly, you guys. You make things so hard for yourselves. I don't
see why that wouldn't just be:

sub infix:!! ($lhs, &rhs) is equiv(&infix:||) {...}

All closures are lazy by definition, and the &rhs forces the right
side of !! to be a closure. At worst, we'd have to change "sub"
to "macro" to give a special parsing rule to the right side.

Larry

Dave Whipp

ulest,
6. apr. 2003, 14:27:3706.04.2003
til perl6-l...@perl.org
Larry Wall wrote:

> Honestly, you guys. You make things so hard for yourselves. I don't
> see why that wouldn't just be:
>
> sub infix:!! ($lhs, &rhs) is equiv(&infix:||) {...}
>
> All closures are lazy by definition, and the &rhs forces the right
> side of !! to be a closure.

A closure may be lazy -- but how would I pass a real closure to a sub?

consider:

sub do_it(&arg) { arg() }

Your statement implies that this can be used as

do_it( $a+$b )

and that the $a+$b will be passed as a closure.

But then we might have a hash of subrefs:

do_it( %commands{$command} )

Will this be passed as a closure; or will the hash lookup be performed?

My personal preference is to avoid this can of worms, and use a trait to
indicate laziness. Then the original sub would be declared:

sub infix:!! ($lhs, $rhs is lazy) {...}

This makes the intent explicit, and does not rely on magic associated
with the & sigil.

To be fair, I chopped the bit where Larry suggested using a macro,
instead of a sub, for the declaration. This would avoid the need for
associating magic with the & sigil; but would preclude having lazy args
to methods.

Dave.

Larry Wall

ulest,
7. apr. 2003, 14:37:5707.04.2003
til perl6-l...@perl.org
On Sun, Apr 06, 2003 at 11:27:37AM -0700, Dave Whipp wrote:
: Larry Wall wrote:
:
: >Honestly, you guys. You make things so hard for yourselves. I don't
: >see why that wouldn't just be:
: >
: > sub infix:!! ($lhs, &rhs) is equiv(&infix:||) {...}
: >
: >All closures are lazy by definition, and the &rhs forces the right
: >side of !! to be a closure.
:
: A closure may be lazy -- but how would I pass a real closure to a sub?
:
: consider:
:
: sub do_it(&arg) { arg() }
:
: Your statement implies that this can be used as
:
: do_it( $a+$b )
:
: and that the $a+$b will be passed as a closure.
:
: But then we might have a hash of subrefs:
:
: do_it( %commands{$command} )
:
: Will this be passed as a closure; or will the hash lookup be performed?

Actually, I was thinking the syntactic closure forcing only applied
to the operator form of an operator definition, since an operator
definition already works a bit like a macro in warping the syntax.
I wasn't thinking that it applied to regular subs, or to operators
called as regular subs. It can't, because otherwise we can't really
do multimethod dispatch correctly on a Code argument. But I didn't
make that explicit in what I said. Sorry.

: My personal preference is to avoid this can of worms, and use a trait to

: indicate laziness. Then the original sub would be declared:
:
: sub infix:!! ($lhs, $rhs is lazy) {...}
:
: This makes the intent explicit, and does not rely on magic associated
: with the & sigil.

There is something to be said for that in any event. But again, it
has to be considered lexically scoped syntactic warpage. We can't
simultaneously make a closure out of it at compile time and then
dispatch multimethods based on the type of what the closure would
return had we evaluated it already, which we haven't.

: To be fair, I chopped the bit where Larry suggested using a macro,

: instead of a sub, for the declaration. This would avoid the need for
: associating magic with the & sigil; but would preclude having lazy args
: to methods.

Lazy args and methods don't mix very well in any event. We're
straining even to get ordinary lists to work right with methods.
That's what the section in A6 on "Context unknown at compile time"
was talking about. Things that simultaneously must be known before
dispatch and can't be known till after dispatch are just a wee bit
problematical.

Larry

0 nye meldinger