omp barrier 是否等同于 Fortran 中的 omp end parallel

Is omp barrier equivalent to omp end parallel in Fortran

我的问题是关于线程同步的。基本上,如果我在 Fortran 中有一个 OpenMP 代码,每个线程都在做某事。我认为同步它们有两种可能性(让一些变量在每个线程中具有相同的值)。

  1. 添加!$OMP BARRIER
  2. 添加 !$OMP END PARALLEL。如有必要,稍后添加 !$OMP PARALLEL!$OMP END PARALLEL 块。

选项 1) 和 2) 是否等效?我在嵌套线程 中看到了一些关于 barrier 的问题 到目前为止,我更喜欢使用 Fortran 的更简单的 scanarios。例如,对于下面的代码,如果我使用 barrier,似乎两个 if (sum > 500) then 条件的行为相同,至少 gfortran.

PROGRAM test
USE OMP_LIB

integer :: numthreads, i, sum



numthreads = 2
sum = 0

call omp_set_num_threads(numthreads)

!$OMP PARALLEL


  if (OMP_GET_THREAD_NUM() == 0) then
    write (*,*) 'a'
    
    do i = 1, 30
      write (*,*) sum
      sum = sum +  i
    end do 

    !write (*,*) 'sum', sum
  else if  (OMP_GET_THREAD_NUM() == 1) then
    write (*,*) 'b'
    do i = 1, 15
      write (*,*) sum
      sum = sum +  i
    end do  
    
    !write (*,*) 'sum', sum    
  end if  

!$OMP BARRIER

  if (sum > 500) then
    write (*,*) 'sum v1'
  else
    write (*,*) 'not yet v1'
  end if

!$OMP END PARALLEL

 
  if (sum > 500) then
    write (*,*) 'sum v2', sum
  else
    write (*,*) 'not yet v2', sum
  end if
 

END

我担心的是,对于代码

blah1 
!$OMP PARALLEL 
!$OMP END PARALLEL
blah2

如果计算机将执行为 blah1 -> omp -> blah2。如果 blah2 中的变量(例如示例代码中的 sum 已经在 omp 块中完全计算,我不需要担心 [=24 中的某些线程=] 会更快,计算条目的一部分(例如,问题中的 sum),然后转到 blah2 部分中的 if 条件,导致一些意外结果。

不,它们根本不等价。

对于 !$omp end parallel,让我们稍微思考一下并行性在 OpenMP 中的工作原理。在您的程序开始时,您只有一个所谓的主线程可用。在您到达一个并行区域之前,情况一直如此,在该区域中您有多个线程可用,主线程和(可能)其他一些线程。在 Fortran 中,并行区域以 !$omp parallel 指令开始。它由 !$omp end parallel 指令关闭,之后您的代码就可以使用主线程,直到您启动另一个并行区域。因此 !$omp end parallel 只是标记平行区域的结束。

在并行区域内,许多 OpenMP 指令开始产生影响。其中之一是 !$omp barrier,它要求给定线程在代码中的那个点等待,直到 all 个线程到达那个点(对于精心选择的“all”值,当诸如嵌套并行之类的东西正在使用中 - 请参阅 https://www.openmp.org/spec-html/5.0/openmpsu90.html 中的标准以获取更多详细信息)。 !$omp barrier 与划定平行区域无关。因此在使用后所有线程仍然可用,并且在并行区域之外它不会有任何效果。

下面的小代码可能有助于说明事情

ijb@ijb-Latitude-5410:~/work/stack$ cat omp_bar.f90
Program omp_bar

  !$ Use omp_lib, Only : omp_get_num_threads, omp_in_parallel

  Implicit None

  Integer n_th
  
  !$omp parallel default( none ) private( n_th )
  n_th = 1
  !$ n_th = omp_get_num_threads()
  Write( *, * ) 'Hello at 1 on ', n_th, ' threads. ', &
       'Are we in a parallel region ?', omp_in_parallel()
  !$omp barrier
  Write( *, * ) 'Hello at 2', omp_in_parallel()
  !$omp end parallel

  Write( *, * ) 'Hello at 3', omp_in_parallel()

End Program omp_bar
ijb@ijb-Latitude-5410:~/work/stack$ gfortran --version
GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@ijb-Latitude-5410:~/work/stack$ gfortran -fopenmp -std=f2008 -Wall -Wextra -fcheck=all -O -g omp_bar.f90 
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
 Hello at 1 on            2  threads. Are we in a parallel region ? T
 Hello at 1 on            2  threads. Are we in a parallel region ? T
 Hello at 2 T
 Hello at 2 T
 Hello at 3 F

[是的,我知道屏障不能保证同步输出顺序,我在这里很幸运]