Reputation: 2639
I have written the following Fortran code to test atomic
and critical
program test
implicit none
integer::i
integer::a(10),b(10),atmp(10),btmp(10)
a=[1,2,3,4,5,6,7,8,9,10]
b=[12,32,54,77,32,19,34,1,75,45]
atmp=a
btmp=b
write(*,'(1X,10I4)') a+b
print*,'------------------'
!$omp parallel
!$omp do
do i=1,10
B(I) = B(I)+A(I)
end do
!$omp end do
!$omp single
write(*,'(1X,10I4)') b
!$omp end single
a=atmp
b=btmp
!$omp do
do i=1,10
!$omp critical
B(I) = B(I)+A(I)
!$omp end critical
end do
!$omp end do
!$omp single
write(*,'(1X,10I4)') b
!$omp end single
a=atmp
b=btmp
!$omp do
do i=1,10
!$omp atomic
B(I) = B(I)+A(I)
!$omp end atomic
end do
!$omp end do
!$omp single
write(*,'(1X,10I4)') b
!$omp end single
!$omp end parallel
end program
The output is
It means that result of atomic
and critical
is wrong. This is strange, I thought adding them could avoid racing condition. However, the first loop without synchronization gives right answer, is there no racing here? What is wrong with my code?
Upvotes: 3
Views: 1207
Reputation: 60078
The problem in your code is the race condition
!$omp parallel
...
a=atmp
b=btmp
...
!$omp end parallel
all threads do that operation and they clash. You want omp single
around these lines.
You don't need any atomic
or critical
in
!$omp do
do i=1,10
B(I) = B(I)+A(I)
end do
!$omp end do
because each thread operates on a different array element.
In your example from the OpenMP specification the issue is that in
!$OMP PARALLEL DO SHARED(X, Y, INDEX, N)
DO I=1,N
!$OMP ATOMIC UPDATE
X(INDEX(I)) = X(INDEX(I)) + WORK1(I)
the array or function INDEX(I)
can return the same value for two different threads with a different I
and you must protect this potential race condition.
Upvotes: 6