Openmp嵌套并行使用可用线程

问题描述 投票:0回答:1

因此,我有一个简单的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.htmlfftw_execute是线程安全的,并且该程序在没有task指令的情况下仍可正常运行。但是使用task会引发错误。有人知道如何解决此问题吗?

因此,我有一个简单的Fortran do循环,在该循环内调用了两个子例程。我已经使do循环与OpenMP并行,像这样!$ omp parallel do do i = 1,n ...

fortran openmp fftw
1个回答
0
投票

遗憾的是,为什么!$omp do parallel是一个坏主意的又一个示例……我确实确实认为最好将线程创建阶段和工作共享阶段明确分开。

© www.soinside.com 2019 - 2024. All rights reserved.