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
system
Closed
March 19, 2025, 7:16pm
7
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.