Matrix 分配矩阵时Fortran Seg错误

Matrix 分配矩阵时Fortran Seg错误,matrix,segmentation-fault,fortran,derived-types,Matrix,Segmentation Fault,Fortran,Derived Types,[更新]代码和几句话已更改,以反映我在第二条评论中解释的实现。代码应该用下面的代码行编译,但是,我有一个较旧的gfortran,可能没有看到您可能看到的一些错误 gfortran BLU_implementation_copy.f90 -o BLU_implementation_copy.x 我在Fortran 90运行时遇到了一个难以置信的不一致seg错误 我的代码的总体目标是将一个随机生成的、复杂的、对称的、对角占优的矩阵分解成易于并行化的块。最后可以找到精简版(相关功能除外) 在函数ma

[更新]代码和几句话已更改,以反映我在第二条评论中解释的实现。代码应该用下面的代码行编译,但是,我有一个较旧的gfortran,可能没有看到您可能看到的一些错误

gfortran BLU_implementation_copy.f90 -o BLU_implementation_copy.x
我在Fortran 90运行时遇到了一个难以置信的不一致seg错误

我的代码的总体目标是将一个随机生成的、复杂的、对称的、对角占优的矩阵分解成易于并行化的块。最后可以找到精简版(相关功能除外)

在函数mat2tiles中将原始矩阵分解为块(tile)时,我遇到了错误。具体而言,这一行代码不断失败:

o(i,j)=单元(x(a:min(i*Nblock,M),b:min(j*Nblock,N))

这是将输入矩阵X的一个块分配给索引i,j处的矩阵o。它实现了这一点,因为o的每个索引都是通过派生类型的矩阵NblockxNblock:

类型单元
复杂*16::块(Nblock,Nblock)
端型单元格

type(cell) :: o(M/Nblock+rem,N/Nblock+rem)
对于特定的矩阵大小和瓷砖大小,一切都可以完美地工作。对于较大的尺寸,错误开始出现在接近矩阵尺寸的瓷砖尺寸中,并最终达到矩阵尺寸的一半。例如,我发现发生这种情况的最小实例是一个20x20矩阵,其平铺大小为18。但这种情况并非始终如一。如果我尝试使用较小的矩阵,这些矩阵都正常运行,并且构建到该大小,它就会运行。如果我做一个更大尺寸的seg故障,然后运行20x20和18,它seg故障。我发现的最小一致参数是25x25,瓷砖大小为23。然而,即使使用这种大小,如果我打印出在o(I,j)赋值行之后失败的块:

print*,o(2,1)%block

它突然毫无问题地贯穿了整个过程。取出print语句使其再次出现seg错误。 最后,最恼人的一个问题[修复-请参阅我的第二条评论],如果我使用一个2000 x2000矩阵,其平铺大小为1000或更大,我在进入函数后会出现seg错误(这意味着它发生在变量分配期间)。这让我相信问题可能源于矩阵是如何分配的,特别是因为我使用的是派生类型。但当我试图诊断矩阵的大小和内容时,一切似乎都正常

program BLU_implementation
    implicit none
    integer :: rem
    integer, parameter :: M=20, N=20, Nblock=19
    real*8 :: start, finish
    complex*16 :: A(M,N)

    type cell
    complex*16 :: block(Nblock,Nblock)
    end type cell

!determines if cell matrix doesn't need to be bigger
    rem=1
    if (modulo(M,Nblock)==0) then
        rem=0
    endif

    call cpu_time(start)
    call functionCalling(A, M, N, Nblock, rem)
    call cpu_time(finish)
    print*, 'overall time:', finish-start, 'seconds'

contains
!==================================================================================================================
subroutine functionCalling(A, M, N, Nblock, rem)
    implicit none
    integer :: IPIV, INFO, M, N, Nblock, rem
    real*8 :: start, finish
    complex*16 :: A(M,N)

    type(cell) :: C(M/Nblock+rem,N/Nblock+rem)

    call cpu_time(start)

    A= CSPDmatrixFill(A,M,N)

    call cpu_time(finish)
    print*, 'matrix fill time:', finish-start, 'seconds'


    call cpu_time(start)

    C= mat2tiles(A,M,N,Nblock,rem) 

    call cpu_time(finish)
    print*, 'tiling time:', finish-start, 'seconds'

end subroutine

!===================================================================================================================
! generates a complex, symmetric, positive-definite matrix (based off of another's code)

function CSPDmatrixFill(A, M, N) result (Matrix)

! initialization  
      implicit none
      integer :: i, j
      integer :: M, N
      real*8 :: x, xi
      complex*16 :: A(M, N), Matrix(M, N), EYE(M, N), MT(N, M)

      EYE=0
      forall(j=1:M) EYE(j,j)=1

! execution

      call random_seed

      do i=1, M
        do j=1, N
          call random_number (x)
            call random_number(xi)
            Matrix(i,j) = cmplx(x,xi)
       end do
      end do  

! construct a symmetric matrix ( O(n^2) )
      call Mtranspose(Matrix, M, N)
      Matrix = Matrix+MT  

! make positive definite (diagonally dominant)
        Matrix = Matrix + N*EYE

end function CSPDmatrixFill

!======================================================================================================
subroutine Mtranspose(A, i, j)
! takes a matrix and the two parameters used to make the matrix: A(i,j)
! returns a matrix with switched indices: A(j,i)
      implicit none

      integer :: i, j
      complex*16 :: A(i,j), MT(j,i)

      MT=A(j,i)
      return
end subroutine Mtranspose

!=======================================================================================================
!MAT2TILES - breaks up an array into a cell array of adjacent sub-arrays of equal sizes
!
! O=mat2tiles(X,M,N,Nblock)
!
!will produce a cell array o containing adjacent chunks of the array X(M,N)
!with each chunk of dimensions NblockxNblock. If Nblock does
!not divide evenly into size(X,i), then the chunks at the upper boundary of
!X along dimension i will have bogus values that do not affect the factorization
!in the places where the matrix doesn't occupy. (according to older versions. Might have changed with some edits)
!
function mat2tiles(X,M,N,Nblock,rem) result(o)

! initialization  
      implicit none
      integer :: a, b, i, j, M, N, Nblock, rem
      complex*16 :: X(M,N)

      type(cell) :: o(M/Nblock+rem,N/Nblock+rem)

! diagnostic print statements
        print*,size(o(1,1)%block), size(o(1,2)%block), size(o(2,1)%block), size(o(2,2)%block)
        print*, 'got to start'

! turn matrix x into cell matrix o

      do j=1, N/Nblock+rem
        if (j==1) then
          b=j
        else 
          b=b+Nblock
        endif       
        do i=1, M/Nblock+rem
          if (i==1) then
            a=i
          else 
            a=a+Nblock
          endif
! diagnostic print statement
          print*, 'writing to o: i:', i, 'j:', j, 'i*Nblock:', i*Nblock, 'j*Nblock:', j*Nblock, 'min of i:', min(i*Nblock, M), &
                    'min of j:', min(j*Nblock, N), 'a:', a, 'b:', b

          o(i,j)=cell(x(a:min(i*Nblock,M), b:min(j*Nblock, N))) 
        enddo
      enddo
! diagnostic print statement
      print*, 'got to end'
      return 
end function mat2tiles

!==================================================================================================
end program

在将问题缩小到使用数字和相同数字的变量之后,人们发现Fortran不喜欢将矩阵分配给不同维度的矩阵,即使它适合内部。这很奇怪,因为较小的
M
N
Nblock
值完美地解决了这个问题

解决方案是简单地定义
o(i,j)%block(1:Nblock,1:Nblock)=x(dim1:dim2等)
而不是
o(i,j)=cell(x(dim1:dim2等)
来表示
i=1
j=1

正确的代码(适用于矩阵大小和磁贴大小的所有情况)如下所示:

if (i==M/Nblock+rem .AND. j==N/Nblock+rem .AND. rem==1) then 
    o(i,j)%block(1:M-(i-1)*Nblock,1:N-(j-1)*Nblock)=x(a:min(i*Nblock,M), b:min(j*Nblock, N))
else if (i==M/Nblock+rem .AND. j/=N/Nblock+rem .AND. rem==1) then
    o(i,j)%block(1:M-(i-1)*Nblock,1:Nblock)=x(a:min(i*Nblock,M), b:min(j*Nblock, N))
else if (i/=M/Nblock+rem .AND. j==N/Nblock+rem .AND. rem==1) then
    o(i,j)%block(1:Nblock,1:N-(j-1)*Nblock)=x(a:min(i*Nblock,M), b:min(j*Nblock, N))
else
    o(i,j)%block(1:Nblock,1:Nblock)=x(a:min(i*Nblock,M), b:min(j*Nblock, N))
end if

通过此更正,我的代码在gfortran的新旧版本上运行。然而,值得注意的是,Mac OS X版本的gfortran从未遇到此错误,只有Linux版本。

您提供的代码甚至没有编译!我收到大量错误消息。请先解决这些问题,也许您的问题会在这个过程。@AlexanderVogt嗨,它为我编译了以下代码行:gfortran BLU_implementation_copy.f90-o BLU_implementation_copy.x~/lapack/liblapack.a~/lapack/librefblas.aHey各位!更新:我发现了部分问题。我的编译器有点旧,没有发现错误。在另一台计算机上,编译器在f中发现了错误CSPDmatrix fill的函数行,其中我为函数定义了“complex”。这与正确的数据类型相冲突,去掉它,2000x2000和1000个磁贴大小的案例运行。但是,其他案例仍然存在seg故障。