为什么实际生成并行进程的OpenMP do-loop,OMP_GET_THREAD_NUM()无法检测到?

时间:2015-06-29 20:07:47

标签: fortran openmp

我无法理解为什么!$ OMP DO实际上是将任务分配给不同的线程但是使用openMP内部函数OMP_GET_THREAD_NUM()无法检测到。

program test
implicit none

integer :: i,su
double precision a(10), b(10),c
INTEGER OMP_GET_THREAD_NUM

su=0


!$OMP DO
do i=1,10
   b(i) = 10*i;
   c = b(i);   
   write(*,*)'in the loop, rank =',c,OMP_GET_THREAD_NUM()
enddo
!$OMP END DO

!$OMP PARALLEL
write(*,*) 'Rank = ',OMP_GET_THREAD_NUM()
!$OMP END PARALLEL

end

结果是:

 in the loop, rank =   10.000000000000000                0
 in the loop, rank =   20.000000000000000                0
 in the loop, rank =   30.000000000000000                0
 in the loop, rank =   40.000000000000000                0
 in the loop, rank =   50.000000000000000                0
 in the loop, rank =   60.000000000000000                0
 in the loop, rank =   70.000000000000000                0
 in the loop, rank =   80.000000000000000                0
 in the loop, rank =   90.000000000000000                0
 in the loop, rank =   100.00000000000000                0
 Rank =            0
 Rank =            6
 Rank =            1
 Rank =            7
 Rank =            2
 Rank =            5
 Rank =            4
 Rank =            3

请参阅?似乎DO-LOOP中只有公共人员可以看到主线程。这是不公平的,因为这不是他唯一的贡献。

1 个答案:

答案 0 :(得分:1)

您的do循环不在并行区域中,因此未并行化 - 所有循环索引都由处理。

如果我将程序更改为包含并行区域

...
!$OMP PARALLEL
!$OMP DO
do i=1,10
   b(i) = 10*i;
   c = b(i);
   write(*,*)'in the loop, rank =',c,OMP_GET_THREAD_NUM()
enddo
!$OMP END DO
!$OMP END PARALLEL
...

然后我得到正确的OMP线程数输出:

 in the loop, rank =   50.000000000000000                8
 in the loop, rank =   20.000000000000000                3
 in the loop, rank =   20.000000000000000                7
 in the loop, rank =   20.000000000000000                4
 in the loop, rank =   20.000000000000000                5
 in the loop, rank =   20.000000000000000                9
 in the loop, rank =   20.000000000000000                6
 in the loop, rank =   20.000000000000000                0
 in the loop, rank =   20.000000000000000                1
 in the loop, rank =   30.000000000000000                2

这个特殊的输出也暴露了代码中的缺陷,即共享c,因此每个线程都会破坏它的值。此外,如果do循环是并行区域中唯一的东西,则可以组合OMP指令。最后,如果我们将您的代码更改为:

!$OMP PARALLEL DO private(c)
do i=1,10
   b(i) = 10*i;
   c = b(i);
   write(*,*)'in the loop, rank =',c,OMP_GET_THREAD_NUM()
enddo
!$OMP END PARALLEL DO

然后输出将是正确的。

 in the loop, rank =   100.00000000000000                9
 in the loop, rank =   30.000000000000000                2
 in the loop, rank =   20.000000000000000                1
 in the loop, rank =   70.000000000000000                6
 in the loop, rank =   60.000000000000000                5
 in the loop, rank =   50.000000000000000                4
 in the loop, rank =   80.000000000000000                7
 in the loop, rank =   90.000000000000000                8
 in the loop, rank =   10.000000000000000                0
 in the loop, rank =   40.000000000000000                3