Fortran DO CONCURRENT REDUCE Implementation help

I am trying to use the new reduce clause with DO CONCURRENT in Fortran. My loop is

      cgdot=0.
      do concurrent (i=1:N) reduce(+:cgdot)
        cgdot=cgdot+x(i)*y(i)
      enddo

I get an error of:

NVFORTRAN-S-1044-Invalid DO CONCURRENT locality spec variable cgdot (pot3d.f: 5415).

I am not sure why exactly. When I compile this as a do concurrent loop like this:

      cgdot=0.
      do concurrent (i=1:N) 
        cgdot=cgdot+x(i)*y(i)
      enddo

The compiler does an implicit reduction:

cgdot:
5415, Generating NVIDIA GPU code
5415, Loop parallelized across CUDA thread blocks, CUDA threads(128) blockidx%x threadidx%x
Generating implicit reduction(+:cgdot)

Am I missing something in the syntax or is that type of loop not supported with reduce?

  • Miko
1 Like

It works for me with 21.11.

$ nvfortran -V

nvfortran 21.11-0 64-bit target on x86-64 Linux -tp zen2 
NVIDIA Compilers and Tools
Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.
 program main
 real, allocatable:: x(:),y(:)
 real:: cgdot
 
 integer:: i,N=1024

 allocate(x(N),y(N)) 
 x=2.
 y=2.
 cgdot=0.
 
 do concurrent(i=1:N ) reduce(+:cgdot)
  cgdot=cgdot+x(i)*y(i)
 end do
 
print *,"Scalar product=",cgdot
 end program main

nvfortran -stdpar cg.f90
$ ./a.out
Scalar product= 4096.000

My function works a little more like this, and if you try compiling, it fails:

program main
 real, allocatable:: x(:),y(:)
 real:: dgdot

 integer:: i,N=1024

 allocate(x(N),y(N))
 x=2.
 y=2.
 dgdot = cgdot(x,y,N)
 print *,"Scalar product=",dgdot
end program main


function cgdot (x,y,N)
   implicit none
   integer :: N,i
   real :: cgdot
   real, dimension(N) :: x,y

   cgdot=0.
   do concurrent (i=1:N) reduce(+:cgdot)
      cgdot=cgdot+x(i)*y(i)
   enddo
   return
end

I think it does not like the name of the function as a reduce argument, let me ask the compiler team ( that told me it is probably a bug, I am going to file one).

This version compiles and runs, you can use this workaround until the issue is fixed.

program main
 real, allocatable:: x(:),y(:)
 real:: dgdot

 integer:: i,N=1024

 allocate(x(N),y(N))
 x=2.
 y=2.
 dgdot = fcgdot(x,y,N)
 print *,"Scalar product=",dgdot

end program main

real function fcgdot (x,y,N)
   implicit none
   integer :: N,i
   real :: cgdot
   real, dimension(N) :: x,y

   cgdot=0.
   do concurrent (i=1:N) reduce(+:cgdot)
      cgdot=cgdot+x(i)*y(i)
   enddo
   fcgdot=cgdot

   return 
end

Thank you for the help. I renamed my variable to tmp and it fixed the issues.

  • Miko
1 Like