回 帖 发 新 帖 刷新版面

主题:请教一个关于LAPACK的问题(环境IVF+MVS+MKL)

大家好,请教一个问题。

我想用LAPACK里面的矩阵奇点分解子程序ZGESVD分解一个矩阵(132*132),但是直接崩溃(不是计算不出结果,而是直接退出程序"segmentation fault"),而如果分解稍小一点的124*124的,那么还可以进行,但是也比较慢(内存占用也非常大)。我认为132*132的矩阵并不算大,真正要分解的矩阵应该是上千的大小。但是132*132的ZGESVD矩阵分解却不是慢而是程序崩溃却很奇怪。

我又实验了类似的子程序ZGGSVD,分解同样的矩阵,却工作正常。甚至更大的也计算正常。让我很不理解,因此上来请教各位,哪里出了问题,我的程序附在后面了。


请各位不吝赐教,先谢谢了!

程序如下运行开始的时候会需要输入wcs的值,矩阵的size=(wcs*2+1)*4,程序会自动生成矩阵并做奇点分解,我调用了ZGGSVD和ZGESVD,wcs<15时一切正常,wcs>=16时ZGGSVD正常,ZGESVD就崩溃了。

    program tryZGESVD
    implicit none
    external zgesvd
    external zggsvd
    
    integer :: Wcs,Sz
    complex(8),dimension(4) :: MtrxElmt
    
    !input and output for ZGGSVD and ZGGSVD
    integer :: lwork,info,SDK,SDL
    real(8),dimension(:),allocatable :: sglV(:),rwork2(:),rwork1(:),alpha,beta
    complex(8),dimension(:,:),allocatable :: SVDU,SVDVt,SVDQ,Mtrx00,Mtrx,Mtrxb
    complex,allocatable,dimension(:) :: work0,work1,work2,iwork
    
    write(*,*) "input Wcs(INTEGER), the size of matirx = (wcs*2+1)*4"
    write(*,*) "if wcs<=15, everything works well, but if wcs>=16, ZGESVD directly crushed"
    read(*,*) wcs
    
    sz=(wcs*2+1)*4

    !Establish Matrix, by the following subroutine, just a sz by sz matrix, which only lower-left block is valued
    allocate(Mtrx00(sz,sz))
    allocate(Mtrx(sz,sz))
    Mtrx00=0
    MtrxElmt=(/-1.0d0,-0.1d0,-0.1d0,-1.0d0/)
    call MFSup1(wcs*2+1,wcs*2+1,2,2,(/Wcs,wcs+1/),(/wcs+1,Wcs/),MtrxElmt,Mtrx00(6*Wcs+4:Sz,1:wcs*2+1))

    
    allocate(SVDU(sz,sz))
    allocate(SVDvt(sz,sz))    
    allocate(SVDQ(sz,sz))

    !zggsvd can give the SVD when wcs>16, i.e. sz>132
    Mtrx=Mtrx00
    allocate(alpha(sz))
    allocate(beta(sz))
    allocate(work1(4*sz))
    allocate(Mtrxb(sz,sz))
    allocate(iwork(sz))
    allocate(rwork1(sz*2))
    Mtrxb=0    
    call zggsvd( "N",  "N",  "Q", sz,sz,sz,SDk,SDl,Mtrx,sz,Mtrxb,sz, alpha, beta,SVDu,sz,SVDvt,sz,SVDQ,sz, work1, rwork1, iwork, info)    
    !write(*,*) "SVDQ",SVDQ(1:sz,1)
    
    !zgesvd can NOT give the SVD when wcs>16, i.e. sz>132
    allocate(sglV(sz))
    allocate(rwork2(sz*5))
    SVDU=0
    SVDvt=0
    Mtrx=Mtrx00
    !call zgesvd( jobu,jobvt, m, n,   a, lda,   s, SVDU, ldu, SVDvt,ldvt,  work, lwork, rwork, info)
    call zgesvd(   "A",  "A",Sz,Sz,Mtrx,  Sz,sglV, SVDU,  Sz, SVDVt,  Sz, rwork2,    -1, rwork2, info)
    lwork=rwork2(1)
    allocate(work0(lwork))
    write(*,*) lwork
    rwork2=0
    Mtrx=Mtrx00
    !call zgesvd( jobu,jobvt, m, n,   a, lda,   s, SVDU, ldu, SVDvt,ldvt,  work, lwork, rwork, info)
    call zgesvd(   "A",  "A",Sz,Sz,Mtrx,  Sz,sglV, SVDU,  Sz, SVDVt,  Sz, work0, lwork, rwork2, info)
    deallocate(work0)
    !write(*,*) "SVDvt",SVDvt(1:sz,1)
    write(*,*) "sglV",sglV
    end program
    
!    ============================================================
    subroutine MFSup1(SizeLTotal,SizeCTotal,BlockL,BlockC,SizeL,sizeC,BlockValue,res)
    !This give all kinds of matrix block.
!    ============================================================
    implicit none
    integer,intent(in) :: SizeLTotal,SizeCTotal,BlockL,BlockC
    integer,intent(in) :: SizeL(BlockL),SizeC(BlockC)
    complex(8),intent(in),dimension(BlockL*BlockC) :: BlockValue
    complex(8),intent(out),dimension(SizeLTotal,SizeCTotal) :: res
    integer :: StartL(BlockL),EndL(BlockL),StartC(BlockC),EndC(BlockC)
    integer :: i1,i2,InitialL,FinalL,InitialC,FinalC

    if (Sum(SizeL).ne.SizeLTotal.or.Sum(SizeC).ne.SizeCTotal) then
        continue
        stop 'MFSup1'
    end if

    InitialL=1
    FinalL=0
    StartL(1)=InitialL
    EndL(BlockL)=SizeLTotal
    do i1=1,BlockL-1
        InitialL=InitialL+SizeL(i1)
        StartL(i1+1)=InitialL
        FinalL=FinalL+SizeL(i1)
        EndL(i1)=FinalL
    end do
    InitialC=1
    FinalC=0
    StartC(1)=InitialC
    EndC(BlockC)=SizeCTotal
    do i1=1,BlockC-1
        InitialC=InitialC+SizeC(i1)
        StartC(i1+1)=InitialC
        FinalC=FinalC+SizeC(i1)
        EndC(i1)=FinalC
    end do

    do i1=1,BlockL
        do i2=1,BlockC
            call MFOri2(SizeL(i1),SizeC(i2),BlockValue((i1-1)*BlockC+i2),res(StartL(i1):EndL(i1),StartC(i2):EndC(i2)))
        end do
    end do

    end subroutine MFSup1
    
!    ============================================================
    subroutine MFOri2(Size1,Size2,DiagE,res)
    !This give the non-square matrix with only semi-diagonal elements.
!    ============================================================
    implicit none
    integer,intent(in) :: size1,Size2
    complex(8),intent(in) :: DiagE
    complex(8),intent(out),dimension(size1,size2) :: res
    integer :: i1,i2,temp
    res=0

    if (size1.gt.size2) then
        temp=size1-size2
        do i1=1,size2
            res(i1,i1)=DiagE
            res(i1+temp,i1)=DiagE
        end do
    else if (size1.lt.size2) then
        temp=size2-size1
        do i1=1,size1
            res(i1,i1)=DiagE
            res(i1,i1+temp)=DiagE
        end do
    else if (size1.eq.size2) then
        do i1=1,size1
            res(i1,i1)=DiagE
        end do
    end if

    end subroutine MFOri2

回复列表 (共2个回复)

沙发

lapack下没有用过这个函数,只能给几点建议. 
segmentation fault 一般是是内存出错(例如分配内存不足或者失败,数组越界等等),在linux里面尝试申请更大使用空间(记得是ulimit命令).
认真对比一下函数要求跟调用是否一直, 特别是那些*work变量, 他们一般是工作空间, 工作空间不足的话可能出错. ZGGSVD: http://www.netlib.no/netlib/lapack/complex16/zggsvd.f

板凳

找到错误了,是我有一个变量声明出了问题,多谢了!

我来回复

您尚未登录,请登录后再回复。点此登录或注册