OpenMP Summation

I am trying to apply OpenMP to a simple sum operation inside two nested loops, but I am getting the wrong result so far. Here I have searched here and here , also in. Everyone suggests using the suggestion reduction

, but that doesn't work for my case, producing a very large number that results in segmentation fault

.

I have also tried this way posted here and my own question here which has been resolved. Both don't use reduction

and just simply set the summation variable as shared

, but also produce an incorrect result. Is there something I am missing? When to use reduction

and not use this when colliding with summation?

Codes using sentence reduction

index = 0
!$OMP PARALLEL DO PRIVATE(iy,ix) REDUCTION(:+index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = index + 1
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

      

Code without using sentence reduction

index = 0
!$OMP PARALLEL DO PRIVATE(iy,ix) SHARED(index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = index + 1
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

      

+3


source to share


1 answer


I think you have the wrong concept of what the proposal is doing reduction

...

REDUCTION(+:index)

      

means you will receive the correct amount at the end index

... At each iteration step, each tread will have a different version with different values! Thus, pruning is not suitable for manipulating array indices in a parallel partition.

Let me illustrate this ...

Next cycle

!$OMP PARALLEL DO PRIVATE(iy) REDUCTION(+:index)
do iy = 1, number(2)
  index = index + 1
end do
!$OMP END PARALLEL DO

      

(more or less) equivalent



!$OMP PARALLEL PRIVATE(iy, privIndex) SHARED(index)
!$OMP DO
do iy = 1, number(2)
  privIndex = privIndex + 1
end do
!$OMP END DO

!$OMP CRITICAL
index = index + privIndex
!$OMP END CRITICAL
!$OMP END PARALLEL

      

You can see that during the loop, all threads operate on different variables privIndex

that are private to that thread and calculate local (partial) sums. In the end, the total is taken using the section critical

to avoid race conditions.

This may not be what the compiler does, but it gives you an idea of ​​how the reduction works: at no point in the first loop privIndex

corresponds to the correct index you would expect in the serial version.


As Vladimir Vladimir suggests in his comment, you can calculate the index directly as you only increment it in the inner loop:

!$OMP PARALLEL DO PRIVATE(iy,ix, index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = (iy-1)*number(1) + ix
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

      

+4


source







All Articles