首页 > 解决方案 > 以编程方式禁用 OpenMP 中的嵌套并行性

问题描述

我面临与此处描述的相同的请求,即我想在第一个子例程中并行化一个“内部”循环,该循环可能会或可能不会从另一个子例程中的“外部”并行化循环调用。在嵌套调用的情况下,我想禁用内部并行化,只保留外部并行化。上述链接中提供的解决方案似乎不起作用。这是一个说明性代码:

program test
  !$ use omp_lib
  !$ write(*,'(A,I0)') "Running OpenMP version ",openmp_version
  write (*,'(A)') 'Direct call to basic:'
  call basic(1)
  write (*,'(A)') 'Iterative call to basic:'
  call iterative()
end program test
!
subroutine basic(i)
  !$ use omp_lib
  integer(kind=4), intent(in) :: i
  integer(kind=4) :: j,level
  !$ level = OMP_GET_ACTIVE_LEVEL()
  !$ write(*,'(A,I0)') "  Basic parallelization level is ",level
  !$OMP PARALLEL SHARED(i) PRIVATE(j) IF(level<1)
  !$OMP DO
  do j=1,3
    write (*,'(A,2I3,A,I0)') "  i,j = ",i,j," done by thread ",omp_get_thread_num()
  enddo
  !$OMP END DO
  !$OMP END PARALLEL
end subroutine basic
!
subroutine iterative()
  !$ use omp_lib
  integer(kind=4) :: i
  !$OMP PARALLEL PRIVATE(i)
  !$OMP DO
  do i=1,2
    write (*,'(2(A,I0))') "  Iterative executes iteration ",i," from thread ",omp_get_thread_num()
    call basic(i)
  enddo
  !$OMP END DO
  !$OMP END PARALLEL
end subroutine iterative

AFAIU,当调用“迭代”时,我面临嵌套的 OMP 循环。由于此处禁用了 OMP 嵌套,因此“内部”循环预计将由调用线程(并且仅调用线程)执行:这就是我想要的。

不幸的是,当我使用 gfortran 9.2.0 执行代码时,我得到:

> gfortran -fopenmp test.f90 -o test && ./test
Running OpenMP version 201511
Direct call to basic:
  Basic parallelization level is 0
  i,j =   1  2 done by thread 1
  i,j =   1  3 done by thread 2
  i,j =   1  1 done by thread 0
Iterative call to basic:
  Iterative executes iteration 2 from thread 1
  Basic parallelization level is 1
  i,j =   2  1 done by thread 0
  i,j =   2  2 done by thread 0
  i,j =   2  3 done by thread 0
  Iterative executes iteration 1 from thread 0
  Basic parallelization level is 1
  i,j =   1  1 done by thread 0
  i,j =   1  2 done by thread 0
  i,j =   1  3 done by thread 0

当直接调用“basic”时,它被正确并行化(线程 0、1 和 2)。当调用“迭代”时,它的主循环很好地并行化(线程 0 和 1)。然后我希望每个调用线程(0和1)执行每个“基本”循环。不幸的是,它们都由线程 0 执行!

如果我编辑代码以从“基本”子例程中删除“OMP PARALLEL IF(条件)”子句(但保留“OMP DO”),则“迭代”调用正常工作(但在调用“基本”时我失去了并行化“ 直接地)。换句话说,当“条件”为假时,“OMP PARALLEL IF(条件)”子句的行为就好像它完全不存在一样。

我对 ifort 18.0.3.222、OpenMP 201611 也有同样的问题。

怎么了?

标签: fortranopenmpnested-loops

解决方案


推荐阅读