与openmp并行化时MEX文件中的分段错误

时间:2015-02-04 11:45:18

标签: matlab fortran openmp mex

我正在尝试使用OpenMP指令并行化FORTRAN90中编写的mex代码。当我不使用任何OpenMP时代码工作正常,但是当我并行化时,我会收到分段错误。我在调试器模式下调试了运行MATLAB的代码。它到达mex函数的末尾没有任何问题,并且当我将结果传递给MATLAB工作区时会产生这个错误。有没有人知道出现这种错误的可能原因?我用的是R2014a。这是代码:

    subroutine qtest(srcRe,srcIm,nF,nS,freq,srcPos,nDim,lstPos,nL,c0,resp)
    use omp_lib
    implicit none
    integer*4, intent(in) :: nF, nS, nDim, nL
    real*8, intent(in)    :: srcRe(nF,nS),srcIm(nF,nS),freq(nF)
    real*8, intent(in)    :: srcPos(nS,nDim), lstPos(nL,nDim), c0
    real*8, intent(out)   :: resp(nF,nL)
    real*8                      :: pi, k(nF), r(nS), x2(nS)
    complex*16                  :: icplx, G(nF), ikr(nF), p(nF)
    integer*4                   :: i,j,m

    icplx   = (0.d0,1.d0)
    pi      = 4.d0*datan(1.d0)
    k       = 2.d0*pi*freq/c0
    resp    = 0.d0
    G       = 0.d0
    !$OMP PARALLEL
    do i = 1,nL
        !$OMP SINGLE
        x2  = (lstPos(i,1) - srcPos(:,1))**2.d0
        r   = x2
        do m = 2,nDim
            r   = r + (lstPos(i,m) - srcPos(:,m))**2.d0
        enddo
        r   = dsqrt(r)
        p   = 0.d0
        !$OMP END SINGLE
        !$OMP DO PRIVATE(j,ikr,G) REDUCTION(+:p)
        do j = 1,nS
            ikr = icplx*k*r(j)
            G   = cdexp(-ikr)/(4.d0*pi*r(j))
            p   = p + (srcRe(:,j) + icplx*srcIm(:,j))*G
        enddo
        !$OMP END DO
        !$OMP SINGLE
        resp(:,i)   = resp(:,i) + 20.d0*dlog10(cdabs(p)/20.d-6)
        !$OMP END SINGLE
    enddo
    !$OMP END PARALLEL
    end subroutine qtest

我用来从/向Matlab工作空间传输变量的函数是:

    #include "fintrf.h"

    !
    SUBROUTINE MEXFUNCTION(NLHS, PLHS, NRHS, PRHS)
    use mexf90
    implicit none
    integer*8, intent(in)   :: PRHS(*)      ! Pointers carrying the input data
    integer*8, intent(out)  :: PLHS(*)      ! Pointers carrying the output data
    integer*4, intent(in)   :: NLHS,NRHS    ! REMAINS THE SAME FOR 64BIT system
    !-----------------------------------------------------------------------
    integer*8               :: err, nF, nF1, nS, nS1, nDim, nDim1, nL
    real*8                  :: c0
    integer*8, pointer      :: srcRe, srcIm, freq, srcPos, lstPos, resp
    character(200)          :: errMsg
    integer*4               :: txt, classId
    integer*4, external     :: mexprintf
    ! ASSIGN POINTERS TO THE VARIOUS PARAMETERS
    srcRe   =>MXGETPR(PRHS(1))
    nF      = MXGETM(PRHS(1))
    nS      = MXGETN(PRHS(1))
    srcIm   =>MXGETPR(PRHS(2))
    freq    =>MXGETPR(PRHS(3))
    nF1     = MXGETM(PRHS(3))
    srcPos  =>MXGETPR(PRHS(4))
    nS1     = MXGETM(PRHS(4))
    nDim    = MXGETN(PRHS(4))
    lstPos  =>MXGETPR(PRHS(5))
    nL      = MXGETM(PRHS(5))
    nDim1   = MXGETN(PRHS(5))
    c0      = MXGETSCALAR(PRHS(6))

    plhs(1) = mxCreateDoubleMatrix(nF,nL,0)
    resp    =>mxGetPr(plhs(1))
    call qtest(srcRe, srcIm,nF,nS,freq,srcPos,nDim,lstPos,nL,c0,resp)

    END SUBROUTINE MEXFUNCTION

调试时,代码到达此行,之后我无法干预任何内容,Matlab进行转移。在Matlab方面,它只是一行调用此函数的代码。

    aaa = qtest(srcRe,srcIm,freq,srcPos,lstPos,c0);

正如我上面提到的,如果我不使用任何并行化,这是有效的。

1 个答案:

答案 0 :(得分:0)

子例程qtest包含声明

integer*4, intent(in) :: nF, nS, nDim, nL

mexfunction包含

integer*8               :: err, nF, nF1, nS, nS1, nDim, nDim1, nL

就个人而言,我始终对变量进行一致的声明,看看会发生什么。