Do concurrent

I am trying to learn how to use do concurrent in fortran. I wrote a basic example, but I don’t understand how to manage total sums:

    do concurrent(i=1:n)
       x(i)=real(i)*0.000137d0
       y(i)=real(i)*0.000029d0
    enddo
    tot=0.0d0
    do concurrent(i=1:n) reduce (+:tot)
       y(i) = x(i)+y(i)+sin(x(i)*y(i))
       tot=tot+y(i)
    enddo

    print*,sum(y)/real(n),tot/real(n)

The final “tot” is not the same as sum(y). What is the right way to use it?
Thanks,
Stefano

1 Like

Hi Stefano,

The syntax looks ok. How different are the two sums?

Parallel reductions will give slightly differing results over a serial reduction. Floating point calculations have a rounding error, so when order of the operations changes, the rounding error changes and hence will give different results.

If the results are very different, please provide a reproducing example that I can build and run.

-Mat

Thank you, the results are quite different. Here the code and the output:

program test
integer :: n=1000000000
real, allocatable :: x(:),y(:)
real :: tot
allocate(x(n),y(n))

    do concurrent(i=1:n)
       x(i)=real(i)*0.000137d0
       y(i)=real(i)*0.000029d0
    enddo
    tot=0.0d0
    do concurrent(i=1:n) reduce (+:tot)
       y(i) = x(i)+y(i)+sin(x(i)*y(i))
       tot=tot+y(i)
    enddo  

    print*,sum(y)/real(n),tot/real(n)

end program

I compile with: nvfortran -O1 -o inizio -stdpar=gpu -Minfo=all -mp=gpu -gpu=cc89 t.f90

Output: 4398.046 83000.00

Thanks,
Stefano

The program is overflowing the default REAL (single precision). Use “real(kind=8)” or add the “-r8” flag to use double precision.

% nvfortran -stdpar=gpu test.F90 -r8
% a.out
    83000.00006749529         83000.00006759127
1 Like

Yes, it works, thank you very much!
Stefano

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.