[Cython] prange CEP updated

mark florisson markflorisson88 at gmail.com
Wed May 4 13:48:07 CEST 2011


On 4 May 2011 13:47, mark florisson <markflorisson88 at gmail.com> wrote:
> 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.
>
 And of course, if you initialize 'i' unconditionally, you change 'i'
whereas you might have to leave it unaffected.


More information about the cython-devel mailing list