Hi Ilmir,

Ilmir Usmanov wrote:
For DO CONCURRENT, it is not.
I always forget about this kind of loops.

And I tend to forget about the issues with mask as I don't use do concurrent with mask.

* And do concurrent also supports masks:

logical :: my_mask(3)
integer :: i, b(3)
b(i) = [5, 5, 2]
my_mask = [.true., .false., .true.]
do concurrent (i=1:3, b(i) == 5 .and. my_mask(i))
  b(i) = -42
end do
end
This is doable: generate mask conditions inside of the deepest for loop (see applied patch). So, GENERIC of your example will be like:
#pragma acc loop collapse(1)
for (i = 1; i < 3; i++)
  {
    if (b[i-1] == 5 && my_mask[i-1])
      {
        b[i-1] = -42;
      }
  }

That will work in the most common cases but not in general. At least it is my understanding that Fortran requires that one first evaluates the mask expression before one enters the loop. That's made explicit for FORALL and DO CONCURRENT uses a forall header and does some refs to FORALL (esp. 7.2.4.2.2 and 7.2.4.2.3), but it does not state so explicitly.

In particular, the following example shows a difference between creating a temporary array for the mask and putting the condition in the loop without a temporary. On my system, the example will give:
           1          -1         -20          -2         -30
         -10          -1         -20          -2         -30

I think you willl get the same result as on line 1 instead of the one of line two. Thus, one will need a temporary (cf. PR60661 for a missed-optimization tracking to avoid the temporary.)


Example:

implicit none
integer :: i, n
integer :: b(5)

n = 5

b = [1, -1, 2, -2, 3]
do i = 1, n
  if (.not. (b(i) > 0)) cycle
  b(n-i+1) = b(n-i+1)*(-10)
end do
print *, b

b = [1, -1, 2, -2, 3]
do concurrent (i = 1:n, b(i) > 0)
  b(n-i+1) = b(n-i+1)*(-10)
end do
print *, b
end

Otherwise, the patch looks good to me.

Tobias

Reply via email to