[Cython] prange CEP updated

mark florisson markflorisson88 at gmail.com
Wed May 4 13:47:12 CEST 2011


On 4 May 2011 13:45, Dag Sverre Seljebotn <d.s.seljebotn at astro.uio.no> wrote:
> On 05/04/2011 01:41 PM, mark florisson wrote:
>>
>> On 4 May 2011 13:39, Dag Sverre Seljebotn<d.s.seljebotn at astro.uio.no>
>>  wrote:
>>>
>>> On 05/04/2011 01:30 PM, mark florisson wrote:
>>>>
>>>> On 4 May 2011 13:15, Dag Sverre Seljebotn<d.s.seljebotn at astro.uio.no>
>>>>  wrote:
>>>>>
>>>>> On 05/04/2011 12:59 PM, mark florisson wrote:
>>>>>>
>>>>>> On 4 May 2011 12:45, Dag Sverre Seljebotn<d.s.seljebotn at astro.uio.no>
>>>>>>  wrote:
>>>>>>>
>>>>>>> On 05/04/2011 12:00 PM, mark florisson wrote:
>>>>>>>>
>>>>>>>> There are two remaining issue. The first is warnings for potentially
>>>>>>>> uninitialized variables for prange(). When you do
>>>>>>>>
>>>>>>>> for i in prange(start, stop, step): ...
>>>>>>>>
>>>>>>>> it generates code like
>>>>>>>>
>>>>>>>> nsteps = (stop - start) / step;
>>>>>>>> #pragma omp parallel for lastprivate(i)
>>>>>>>> for (temp = 0; temp<        nsteps; temp++) {
>>>>>>>>     i = start + temp * step;
>>>>>>>>     ...
>>>>>>>> }
>>>>>>>>
>>>>>>>> So here it will complain about 'i' being potentially uninitialized,
>>>>>>>> as
>>>>>>>> it might not be assigned to in the loop. However, simply assigning 0
>>>>>>>> to 'i' can't work either, as you expect zero iterations not to touch
>>>>>>>> it. So for now, we have a bunch of warnings, as I don't see a
>>>>>>>> __attribute__ to suppress it selectively.
>>>>>>>
>>>>>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your
>>>>>>> testcase
>>>>>>> could get such a warning? If so, the fix is simply to initialize i in
>>>>>>> your
>>>>>>> testcase code.
>>>>>>
>>>>>> No, the problem is that 'i' needs to be lastprivate, and 'i' is
>>>>>> assigned to in the loop body. It's irrelevant whether 'i' is assigned
>>>>>> to before the loop. I think this is the case because the spec says
>>>>>> that lastprivate variables will get the value of the private variable
>>>>>> of the last sequential iteration, but it cannot at compile time know
>>>>>> whether there might be zero iterations, which I believe the spec
>>>>>> doesn't have anything to say about. So basically we could guard
>>>>>> against it by checking if nsteps>      0, but the compiler doesn't
>>>>>> detect
>>>>>> this, so it will still issue a warning even if 'i' is initialized (the
>>>>>> warning is at the place of the lastprivate declaration).
>>>>>
>>>>> Ah. But this is then more important than I initially thought it was.
>>>>> You
>>>>> are
>>>>> saying that this is the case:
>>>>>
>>>>> cdef int i = 0
>>>>> with nogil:
>>>>>    for i in prange(n):
>>>>>        ...
>>>>> print i # garbage when n == 0?
>>>>
>>>> I think it may be, depending on the implementation. With libgomp it
>>>> return 0. With the check it should also return 0.
>>>>
>>>>> It would be in the interest of less semantic differences w.r.t. range
>>>>> to
>>>>> deal better with this case.
>>>>>
>>>>> Will it silence the warning if we make "i" firstprivate as well as
>>>>> lastprivate? firstprivate would only affect the case of zero
>>>>> iterations,
>>>>> since we overwrite with NaN if the loop is entered...
>>>>
>>>> Well, it wouldn't be NaN, it would be start + step * temp :) But, yes,
>>>
>>> Doh.
>>>
>>>> that works. So we need both the check and an initialization in there:
>>>>
>>>> if (nsteps>    0) {
>>>>     i = 0;
>>>>     #pragma omp parallel for firstprivate(i) lastprivate(i)
>>>>     for (temp = 0; ...; ...) ...
>>>> }
>>>
>>> Why do you need the if-test? Won't simply
>>>
>>> #pragma omp parallel for firstprivate(i) lastprivate(i)
>>> for (temp = 0; ...; ...) ...
>>>
>>> do the job -- any initial value will be copied into all threads,
>>> including
>>> the "last" thread, even if there are no iterations?
>>
>> It will, but you don't expect your iteration variable to change with
>> zero iterations.
>
> Look.
>
> i = 42
> for i in prange(n):
>    f(i)
> print i # want 42 whenever n == 0
>
> Now, translate this to:
>
> i = 42;
> #pragma omp parallel for firstprivate(i) lastprivate(i)
> for (temp = 0; ...; ...) {
>    i = ...
> }
> #pragma omp parallel end
> /* At this point, i == 42 if n == 0 */
>
> Am I missing something?

Yes, 'i' may be uninitialized with nsteps > 0 (this should be valid
code). So if nsteps > 0, we need to initialize 'i' to something to get
correct behaviour with firstprivate.


More information about the cython-devel mailing list