omp barrier 是否等同于 Fortran 中的 omp end parallel
Is omp barrier equivalent to omp end parallel in Fortran
我的问题是关于线程同步的。基本上,如果我在 Fortran
中有一个 OpenMP
代码,每个线程都在做某事。我认为同步它们有两种可能性(让一些变量在每个线程中具有相同的值)。
- 添加
!$OMP BARRIER
- 添加
!$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
[是的,我知道屏障不能保证同步输出顺序,我在这里很幸运]
我的问题是关于线程同步的。基本上,如果我在 Fortran
中有一个 OpenMP
代码,每个线程都在做某事。我认为同步它们有两种可能性(让一些变量在每个线程中具有相同的值)。
- 添加
!$OMP BARRIER
- 添加
!$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
[是的,我知道屏障不能保证同步输出顺序,我在这里很幸运]