【发布时间】:2025-12-23 12:40:11
【问题描述】:
所以,我有一个简单的 Fortran do 循环,并且在该循环内调用了几个子例程。我有 使 do 循环与 OpenMP 并行,像这样
!$omp parallel do
do i=1,n
call a()
call b()
enddo
!$omp end parallel do
现在大多数时候循环中的迭代次数是
与可用的处理器/线程的数量以及在内部调用的子例程相比更少
循环可以并行调用。那么,有没有办法在并行内部并行调用子例程
做循环?我试过像这样使用task
!$omp parallel do
do i=1,n
!$omp task
call a(i , j )
!$omp end task
!$omp task
call b(i, k)
!$omp end task
!$omp taskwait
enddo
!$omp end parallel do
但这表明segmentation fault 存在一些错误。有什么办法可以做到这一点。
更新:
所以,我发现分段错误的主要原因来自 fftw 库。让我们考虑一个虚拟程序
program name
!$use omp_lib
implicit real*8(a-h,p-z)
call system_clock(count_rate=irate)
call system_clock(it1)
!$ call omp_set_nested(.true.)
!$omp parallel do
do i =1,5
call test(i)
print *, i
enddo
!$omp end parallel do
call system_clock(it2)
print *, (it2-it1)/real(irate, kind=8)
end program name
subroutine test(ii)
! just a dummy subroutine for heavy computation
implicit real*8(a-h,p-z)
do j=1,40000
!$omp task
do k=1,40000
x = exp(sqrt(sqrt(2.0d0*ii**3)**2))
enddo
!$omp end task
enddo
end subroutine
这个程序完全符合我的要求并使用任务指令,使用剩余的线程并提高性能。现在让我们考虑另一个虚拟程序,但使用 fftw,类似于我的工作。
program name
!$use omp_lib
implicit real*8(a-h,p-z)
integer, parameter :: n=8192*8
complex(kind=8) :: arr(n)
real(kind=8) :: tmp1(n), tmp2(n)
integer(kind=8) :: pF
integer :: i
call system_clock(count_rate=irate)
call dfftw_plan_dft_1d(pF,n,arr,arr,-1,0) ! forward
call system_clock(it1)
!$ call omp_set_nested(.true.)
!$omp parallel do private(arr)
do i =1,5
call random_number(tmp1)
call random_number(tmp2)
arr = cmplx(tmp1, tmp2, kind=8)
call test(pF, arr)
print *, i
enddo
!$omp end parallel do
call system_clock(it2)
print *, (it2-it1)/real(irate, kind=8)
end program name
subroutine test(pF, arr)
implicit real*8(a-h,p-z)
complex(kind=8) :: arr(:)
integer(kind=8) :: pF
do j=1,100
!$omp task private(arr)
do k=1, 100
call dfftw_execute_dft(pF, arr, arr)
enddo
!$omp end task
enddo
end subroutine
现在,这会引发分段错误。 (注意:我的实际程序中没有随机数字调用,它们在这里只是为了一个虚拟目的)。我检查了http://www.fftw.org/fftw3_doc/Thread-safety.html 和fftw_execute 是线程安全的,并且程序在没有task 指令的情况下工作。但是使用 task 它会引发错误。有谁知道如何解决这个问题?
【问题讨论】:
-
我能找到的所有示例都涉及任务子句周围的
$omp parallel和$omp single。你试过吗?我会先让它在没有外部并行循环的情况下工作。完成后,添加回外部循环并在 OpenMP 中启用嵌套并行,它应该可以按预期工作。 -
"some error with
segmentation fault" 如果你对错误的解释感兴趣,你必须展示更多,否则我们可以告诉你,你有 一些代码中的问题。您是否启用了嵌套并行性?如何?任务还不够吗?为什么不完全删除parallel do? -
我已经用新的细节更新了问题,请检查。
-
请修正隐式 real*8 和 kind=8,它们是对现代 Fortran 实践的厌恶。它在哪里出现故障?为什么你的任务有 private(arr)?