简体   繁体   English

在Fortran中使用SCALAPACK的分段错误? 没有回溯?

[英]Segmentation fault using SCALAPACK in Fortran? No backtrace?

I'm trying to find the eigenvalues and eigenvectors of a Hermitian matrix using SCALAPACK and MPI in Fortran. 我正在尝试在Fortran中使用SCALAPACK和MPI查找Hermitian矩阵的特征值和特征向量。 For bug-squashing, I made this program as simple as possible, but am still getting a segmentation fault. 对于压错程序,我使该程序尽可能简单,但仍然遇到分段错误。 Per the answers given to people with similar questions, I've tried changing all of my integers to integer*8, and all of my reals to real*8 or real*16, but I still get this issue. 根据给有类似问题的人的答案,我尝试将所有整数更改为integer * 8,并将所有实数更改为real * 8或real * 16,但仍然遇到此问题。 Most interestingly, I don't even get a backtrace for the segmentation fault: the program hangs up when trying to give me a backtrace and has to be aborted manually. 最有趣的是,我什至没有遇到分段错误的回溯:试图给我回溯的程序挂起,必须手动中止。

Also, please forgive my lack of knowledge -- I'm not familiar with most program-y things but I've done my best. 另外,请原谅我缺乏的知识-我不熟悉大多数程序化的东西,但是我已经尽力了。 Here is my code: 这是我的代码:

    PROGRAM easydiag
    IMPLICIT NONE 
  INCLUDE 'mpif.h'
  EXTERNAL BLACS_EXIT, BLACS_GET, BLACS_GRIDEXIT, BLACS_GRIDINFO
  EXTERNAL BLACS_GRIDINIT, BLACS_PINFO,BLACS_SETUP, DESCINIT 
  INTEGER,EXTERNAL::NUMROC,ICEIL
  REAL*8,EXTERNAL::PDLAMCH

  INTEGER,PARAMETER::XNDIM=4 ! MATRIX WILL BE XNDIM BY XNDIM
  INTEGER,PARAMETER::EXPND=XNDIM
  INTEGER,PARAMETER::NPROCS=1

  INTEGER COMM,MYID,ROOT,NUMPROCS,IERR,STATUS(MPI_STATUS_SIZE)
  INTEGER NUM_DIM
  INTEGER NPROW,NPCOL
  INTEGER CONTEXT, MYROW, MYCOL

  COMPLEX*16,ALLOCATABLE::HH(:,:),ZZ(:,:),MATTODIAG(:,:)
  REAL*8:: EIG(2*XNDIM) ! EIGENVALUES
  CALL MPI_INIT(ierr)
  CALL MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)
  CALL MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)
  ROOT=0

  NPROW=INT(SQRT(REAL(NPROCS)))
  NPCOL=NPROCS/NPROW   
  NUM_DIM=2*EXPND/NPROW

  CALL SL_init(CONTEXT,NPROW,NPCOL)
  CALL BLACS_GRIDINFO( CONTEXT, NPROW, NPCOL, MYROW, MYCOL )

  ALLOCATE(MATTODIAG(XNDIM,XNDIM),HH(NUM_DIM,NUM_DIM),ZZ(NUM_DIM,NUM_DIM))
  MATTODIAG=0.D0

  CALL MAKEHERMMAT(XNDIM,MATTODIAG)

  CALL MPIDIAGH(EXPND,MATTODIAG,ZZ,MYROW,MYCOL,NPROW,NPCOL,NUM_DIM,CONTEXT,EIG)


  DEALLOCATE(MATTODIAG,HH,ZZ)




   CALL MPI_FINALIZE(IERR)


END

!****************************************************
SUBROUTINE MAKEHERMMAT(XNDIM,MATTODIAG)
  IMPLICIT NONE
  INTEGER:: XNDIM, I, J, COUNTER
  COMPLEX*16:: MATTODIAG(XNDIM,XNDIM)
  REAL*8:: RAND

  COUNTER = 1
  DO J=1,XNDIM
    DO I=J,XNDIM
        MATTODIAG(I,J)=COUNTER
        COUNTER=COUNTER+1
    END DO
  END DO




END
!****************************************************
SUBROUTINE MPIDIAGH(EXPND,A,Z,MYROW,MYCOL,NPROW,NPCOL,NUM_DIM,CONTEXT,W)
    IMPLICIT NONE
  EXTERNAL DESCINIT 
  REAL*8,EXTERNAL::PDLAMCH

  INTEGER EXPND,NUM_DIM
  INTEGER CONTEXT
  INTEGER MYCOL,MYROW,NPROW,NPCOL
  COMPLEX*16 A(NUM_DIM,NUM_DIM), Z(NUM_DIM,NUM_DIM)
  REAL*8 W(2*EXPND)

  INTEGER N
  CHARACTER JOBZ, RANGE, UPLO
  INTEGER IL,IU,IA,JA,IZ,JZ
  INTEGER LIWORK,LRWORK,LWORK
  INTEGER M, NZ, INFO

  REAL*8  ABSTOL, ORFAC, VL, VU

  INTEGER DESCA(50), DESCZ(50)
  INTEGER IFAIL(2*EXPND), ICLUSTR(2*NPROW*NPCOL)
  REAL*8 GAP(NPROW*NPCOL)
  INTEGER,ALLOCATABLE:: IWORK(:)
  REAL*8,ALLOCATABLE :: RWORK(:)
  COMPLEX*16,ALLOCATABLE::WORK(:)

  N=2*EXPND
  JOBZ='V'
  RANGE='I'
  UPLO='U' ! This should be U rather than L
  VL=0.d0
  VU=0.d0
  IL=1  ! EXPND/2+1
  IU=2*EXPND  !  EXPND+(EXPND/2)   ! HERE IS FOR THE CUTTING OFF OF THE STATE
  M=IU-IL+1
  ORFAC=-1.D0
  IA=1
  JA=1
  IZ=1
  JZ=1


  ABSTOL=PDLAMCH( CONTEXT, 'U')
  CALL DESCINIT( DESCA, N, N, NUM_DIM, NUM_DIM, 0, 0, CONTEXT, NUM_DIM, INFO )
  CALL DESCINIT( DESCZ, N, N, NUM_DIM, NUM_DIM, 0, 0, CONTEXT, NUM_DIM, INFO )



  LWORK = -1
  LRWORK = -1
  LIWORK = -1
  ALLOCATE(WORK(LWORK))
  ALLOCATE(RWORK(LRWORK))
  ALLOCATE(IWORK(LIWORK))


  CALL PZHEEVX( JOBZ, RANGE, UPLO, N, A, IA, JA, DESCA, VL, &
                VU, IL, IU, ABSTOL, M, NZ, W, ORFAC, Z, IZ, &
                JZ, DESCZ, WORK, LWORK, RWORK, LRWORK, IWORK, &
                LIWORK, IFAIL, ICLUSTR, GAP, INFO )

  LWORK = INT(ABS(WORK(1)))
  LRWORK = INT(ABS(RWORK(1)))
  LIWORK =INT (ABS(IWORK(1)))

  DEALLOCATE(WORK)
  DEALLOCATE(RWORK)
  DEALLOCATE(IWORK)

  ALLOCATE(WORK(LWORK))
  ALLOCATE(RWORK(LRWORK))
  ALLOCATE(IWORK(LIWORK))


         PRINT*, LWORK, LRWORK, LIWORK

  CALL PZHEEVX( JOBZ, RANGE, UPLO, N, A, IA, JA, DESCA, VL, &
                VU, IL, IU, ABSTOL, M, NZ, W, ORFAC, Z, IZ, &
                JZ, DESCZ, WORK, LWORK, RWORK, LRWORK, IWORK, &
                LIWORK, IFAIL, ICLUSTR, GAP, INFO )





  RETURN
END

The problem is with the second PZHEEVX function. 问题出在第二个PZHEEVX功能上。 I'm fairly certain that I'm using it correctly since this code is a simpler version of another more complicated code that works fine. 我可以肯定我正确使用了它,因为此代码是另一个可以正常工作的更复杂代码的简单版本。 For this purpose, I'm only using one processor. 为此,我仅使用一个处理器。

Help! 救命!

According to this page setting LWORK = -1 seems to request the PZHEEVX routine to return the necessary size of all the work arrays, for example, 根据此页面,设置LWORK = -1似乎请求PZHEEVX例程返回所有工作数组的必要大小,例如,

If LWORK = -1, then LWORK is global input and a workspace query is assumed; 如果LWORK = -1,则LWORK是全局输入,并假定一个工作区查询; the routine only calculates the optimal size for all work arrays. 该例程仅计算所有工作数组的最佳大小。 Each of these values is returned in the first entry of the corresponding work array, and no error message is issued by PXERBLA. 这些值中的每一个都在相应工作数组的第一个条目中返回,并且PXERBLA不会发出错误消息。

Similar explanations can be found for LRWORK = -1. 对于LRWORK = -1,可以找到类似的解释。 As for IWORK, 至于IWORK,

IWORK (local workspace) INTEGER array On return, IWORK(1) contains the amount of integer workspace required. IWORK(本地工作空间)INTEGER数组返回时,IWORK(1)包含所需的整数工作空间量。

but in your program the work arrays are allocated as 但是在您的程序中,工作数组分配为

LWORK = -1
LRWORK = -1
LIWORK = -1
ALLOCATE(WORK(LWORK))
ALLOCATE(RWORK(LRWORK))
ALLOCATE(IWORK(LIWORK))

and after the first call of PZHEEVX, the sizes of the work arrays are obtained as 在第一次调用PZHEEVX之后,工作数组的大小为

LWORK = INT(ABS(WORK(1)))
LRWORK = INT(ABS(RWORK(1)))
LIWORK =INT (ABS(IWORK(1)))

which looks inconsistent (-1 vs 1). 看起来不一致(-1比1)。 So it will be better to modify the allocation as (*) 因此最好将分配修改为(*)

allocate( WORK(1), RWORK(1), IWORK(1) )

An example in this page also seems to allocate the work arrays this way. 此页面中的示例似乎也以这种方式分配工作数组。 Another point of concern is that INT() is used in several places (for example, NPROW=INT(SQRT(REAL(NPROCS))) , but I guess it might be better to use NINT() to avoid the effect of round-off errors. 另一个需要注意的地方是INT()在多个地方使用(例如NPROW=INT(SQRT(REAL(NPROCS))) ,但我想最好使用NINT()来避免NPROW=INT(SQRT(REAL(NPROCS)))入的影响。错误。

(*) More precisely, allocation of an array with -1 is not valid because the size of an allocated array becomes 0 (thanks to @francescalus). (*)更准确地说,使用-1分配数组无效,因为分配的数组的大小变为0(由于@francescalus)。 You can verify this by printing size(a) or a(:). 您可以通过打印size(a)或a(:)来进行验证。 To prevent this kind of error, it is very useful to attach compiler options like -fcheck=all (for gfortran) or -check (for ifort). 为防止此类错误,附加-fcheck = all(对于gfortran)或-check(对于ifort)等编译器选项非常有用。

There's a fishy piece of dimensioning in your code which can easily be responsible for the segfault. 您的代码中有一个糟糕的尺寸标注,很容易造成段错误。 In your main program you set 在主程序中设置

EXPND=XNDIM=4
NUM_DIM=2*EXPND !NPROW==1 for a single-process test
ALLOCATE(MATTODIAG(XNDIM,XNDIM))   ! MATTODIAG(4,4)

Then you pass your MATTODIAG , the Hermitian matrix, to 然后,您将MATTODIAG (厄米矩阵)传递给

CALL MPIDIAGH(EXPND,MATTODIAG,ZZ,MYROW,...)

which is in turn defined as 依次定义为

SUBROUTINE MPIDIAGH(EXPND,A,Z,MYROW,...)

COMPLEX*16 A(NUM_DIM,NUM_DIM)   ! A(8,8)

This is already an inconsistency, which can mess up the computations in that subroutine (even without having a segfault). 这已经是一个不一致的地方,它可能会使该子例程中的计算混乱(即使没有分段错误)。 Furthermore, the subroutine along with scalapack thinks that A is of size (8,8) , instead of (4,4) which you allocated in the main program, allowing the subroutine to overrun available memory. 此外,该子例程与scalapack一起认为A的大小为(8,8) ,而不是您在主程序中分配的大小(8,8) (4,4) ,从而使该子例程溢出了可用内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM