[Cython] prange CEP updated

Robert Bradshaw robertwb at math.washington.edu
Thu Apr 21 21:04:24 CEST 2011


On Thu, Apr 21, 2011 at 11:13 AM, Dag Sverre Seljebotn
<d.s.seljebotn at astro.uio.no> wrote:
> On 04/21/2011 10:37 AM, Robert Bradshaw wrote:
>>
>> In terms of the CEP, I'm still unconvinced that firstprivate is not
>> safe to infer, but lets leave the initial values undefined rather than
>> specifying them to be NaNs (we can do that as an implementation if you
>> want), which will give us flexibility to change later once we've had a
>> chance to play around with it.
>
> I don't see any technical issues with inferring firstprivate, the question
> is whether we want to. I suggest not inferring it in order to make this
> safer: One should be able to just try to change a loop from "range" to
> "prange", and either a) have things fail very hard, or b) just work
> correctly and be able to trust the results.
>
> Note that when I suggest using NaN, it is as initial values for EACH
> ITERATION, not per-thread initialization. It is not about "firstprivate" or
> not, but about disabling thread-private variables entirely in favor of
> "per-iteration" variables.
>
> I believe that by talking about "readonly" and "per-iteration" variables,
> rather than "thread-shared" and "thread-private" variables, this can be used
> much more safely and with virtually no knowledge of the details of
> threading. Again, what's in my mind are scientific programmers with (too)
> little training.
>
> In the end it's a matter of taste and what is most convenient to more users.
> But I believe the case of needing real thread-private variables that
> preserves per-thread values across iterations (and thus also can possibly
> benefit from firstprivate) is seldomly enough used that an explicit
> declaration is OK, in particular when it buys us so much in safety in the
> common case.
>
> To be very precise,
>
> cdef double x, z
> for i in prange(n):
>    x = f(x)
>    z = f(i)
>    ...
>
> goes to
>
> cdef double x, z
> for i in prange(n):
>    x = z = nan
>    x = f(x)
>    z = f(i)
>    ...
>
> and we leave it to the C compiler to (trivially) optimize away "z = nan".
> And, yes, it is a stopgap solution until we've got control flow analysis so
> that we can outright disallow such uses of x (without threadprivate
> declaration, which also gives firstprivate behaviour).

OK, I had totally missed that these are per-iteration. In that case,
it makes more sense.

>> The "cdef threadlocal(int) foo" declaration syntax feels odd to me...
>> We also probably want some way of explicitly marking a variable as
>> shared and still be able to assign to/flush/sync it. Perhaps the
>> parallel context could be used for these declarations, i.e.
>>
>>     with parallel(threadlocal=a, shared=(b,c)):
>>         ...
>>
>> which would be considered an "expert" usecase.
>
> I'm not set on the syntax for threadlocal variables; although your proposal
> feels funny/very unpythonic, almost like a C macro. For some inspiration,
> here's the Python solution (with no obvious place to put the type):
>
> import threading
> mydata = threading.local()
> mydata.myvar = ... # value is threadprivate

That's nice and Pythonic, though I'm not sure how we would handle
typing and the passing of "mydata" around if we wanted to go that
route. We have cython.locals, we could introduce
cython.parallel.threadlocals(a=int), though this is a bit magical as
well.

>> For all the discussion of threadsavailable/threadid, the most common
>> usecase I see is for allocating a large shared buffer and partitioning
>> it. This seems better handled by allocating separate thread-local
>> buffers, no? I still like the context idea, but everything in a
>> parallel block before and after the loop(s) also seems like a natural
>> place to put any setup/teardown code (though the context has the
>> advantage that __exit__ is always called, even if exceptions are
>> raised, which makes cleanup a lot easier to handle).
>
> I'd *really* like to have try/finally available in cython.parallel block for
> this, although I realize that may have to wait for a while. A big part of
> our discussions at the workshop were about how to handle exceptions; I guess
> there'll be a "phase 2" of this where break/continue/raise is dealt with.

Yeah, this is definitely an (important) second or third phase.

- Robert


More information about the cython-devel mailing list