【问题标题】:Fortran array allocation deletion now incorrect solutionFortran 数组分配删除现在不正确的解决方法
【发布时间】:2013-07-02 06:02:53
【问题描述】:

我正在编写一个程序。该程序求解矩阵。矩阵与用户在命令行参数中指定的一样大。我希望程序解决非常大的矩阵,所以当我完成所有线性代数的东西,包括 umfpack、lapack、suitespares、arpack ......我试图通过删除未使用的数组来释放内存空间。我找到了 3 个完全未使用的数组,它们仅用于调试解决矩阵的其他问题。

当我从声明和分配中删除变量时,程序开始表现不同。矩阵解决方案现在是错误的。我已经回到我的备份文件,它仍然可以正常工作。我确信删除未使用数组的声明和分配会阻止我的程序找到正确的解决方案。

这几天我一直在玩弄这个问题。我真的无法想象删除未使用的数组会如何改变我的程序的执行。任何帮助表示赞赏。

 program HHSolver
    use MathOperations
    integer :: O, NEV, i, j, k, a, col, row
    integer :: coeff, p, b, NTerms, NextCoeff
    integer :: m, n, symbolic, numeric
    integer :: TermIndex, ido, NCV,LDV, LWorkL, info2,ierr
    double precision :: x, y, sigmai, sigmar
    Character(128) :: String, term, factor
    character(1) :: bmat
    character(2) :: which
    double precision, dimension(:, :), allocatable :: polynomial        !this stores the polynomial boundary equation      
    double precision, dimension(:, :), allocatable :: lap           !this stores the polynomial boundary equation      
    double precision, dimension(:, :), allocatable :: temp          !this stores the polynomial boundary equation      
    double precision, dimension(:, :), allocatable :: R         !this stores the polynomial boundary equation           
    double precision, dimension(:, :), allocatable :: vec           !this stores the polynomial boundary equation           
    double precision, dimension(:, :), allocatable :: lwork         !this stores the polynomial boundary equation           
    double precision, dimension(:), allocatable :: alphar, beta 
    double precision, dimension(:), allocatable :: alphai, work 
    double precision, dimension(1, 1) :: dummy
    double precision, dimension(:), allocatable :: RESID        
    double precision, dimension(:, :), allocatable :: V, z
    double precision, dimension(:), allocatable :: workd, workl
    double precision, dimension(:), allocatable :: workev
    double precision, dimension(:), allocatable :: Ax, DI, DR
    integer, dimension(:), allocatable :: Ap, Ai
    integer, dimension(11) :: IPARAM
    integer, dimension(14) :: IPNTR     
    integer, dimension(1) :: h
    double precision :: control(20), info(90), tol
    logical, dimension(:), allocatable :: select
    logical :: rvec(1)
    double precision, dimension(:), allocatable :: tempvec

    external daxpy, dnrm2, dpttrf, dpttrs, dlapy2
    intrinsic abs

    call get_command_argument(1, String)
    read(String, '(i10)') O
    call get_command_argument(2, String)
    read(String, '(i10)') NEV
    call get_command_argument(3, String)

    write(*, *) 'try to allocate enough memory for full matrices'

    !this is wh the matrix is created
    allocate(lap((O + 1)**2, (O + 1)**2)) !this stores the polynomial boundary equation             
    allocate(temp((O + 1)**2, (O + 1)**2)) !this stores the polynomial boundary equation            
    allocate(R((O + 1)**2, (O + 1)**2)) !this stores the polynomial boundary equation           
    allocate(alphar((O+1)**2)) !this stores the polynomial boundary equation            
    allocate(alphai((O+1)**2)) !this stores the polynomial boundary equation            
    allocate(beta((O+1)**2)) !this stores the polynomial boundary equation              
    allocate(vec((O + 1)**2, (O + 1)**2)) !this stores the polynomial boundary equation             
    allocate(work(8*((O+1)**2))) !this stores the polynomial boundary equation              
    allocate(lwork(2*((O+1)**2), 2*((O+1)**2))) !this stores the polynomial boundary equation           
    allocate(RESID((O+1)**2)) !this stores the initial and last eigenvector
    allocate(V((O+1)**2,20+NEV)) !this stores the eigenvectors
    allocate(workd(3*((O+1)**2))) !this stores the eigenvectors             
    allocate(workl(30*(20+NEV)**2 + 60*(20+NEV))) !this stores the eigenvectors             
    allocate(workev(3*(20+NEV))) !this stores the eigenvectors              
    allocate(tempvec((O+1)**2)) !this stores the eigenvectors               
    allocate(DI(NEV+1)) !this stores the eigenvectors               
    allocate(DR(NEV+1)) !this stores the eigenvectors               
    allocate(select(20+NEV)) !this stores the eigenvectors              
    allocate(z((O+1)**2,1+NEV)) !this stores the eigenvectors

    write(*, *) 'memory for matrices allocated'     

            !create the matrix to be solved
            !solver the matrix

    write(*, '(25F20.5)') DI   !these are the real and imaginary part of solution
    write(*, '(25F20.5)') DR
  end program

当我尝试删除 alphai、alphar、lwork 时,一切都崩溃了。它们甚至没有被使用。

【问题讨论】:

  • 请提供一些代码开始,这样更容易找出问题所在
  • 它没有让我。它不喜欢这种格式。我不会更改 1000 行代码的格式。
  • 如果将implicit none 语句放在第 3 行会发生什么?

标签: arrays matrix fortran gfortran


【解决方案1】:

您描述:未使用的数组,如果您删除,您的程序会给出错误的答案。一种可能性是使用的其他一些数组被声明得太小。在删除使用的数组之后,这些数组在内存中重叠并且由于重叠而被错误地更改。以前,当您拥有额外的阵列时,幸运的是,它们为阵列或太小的阵列提供了额外的存储空间。

您可以通过初始化未使用的数组来测试这一点,然后在程序结束时查看它们的值是否发生了变化。

您可以查看所有数组的维度。

在模块中包含所有过程(子例程和函数)以便编译器知道它们的接口将允许编译器检查调用它们的实际参数与其虚拟参数之间的一致性。 external 声明表明您没有使用 Fortran >=90 提供的此帮助。

使用编译器的所有错误和警告选项,包括运行时下标检查,可能会发现问题。如果数组以某种方式传递给子例程,导致其尺寸信息丢失,这可能无济于事。使用 gfortran,尝试:-fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -fbacktrace

【讨论】:

  • 这是我的推测性解释。未使用的数组实际上是在创建一个缓冲区,其中一个函数超出了边界数组的边界。我会认为这会导致运行时错误。我可以分配(a(10)),分配(b(10))并将某些内容存储在a(11)= b(1)中而不会发生任何错误,这似乎很奇怪。
  • 默认不检查下标使用的正确性。该检查需要额外的指令,这些指令具有运行时成本。使用 gfortran,您可以使用 -fcheck=all(包括 -fcheck=bounds)添加此检查。它可能会也可能不会发现下标错误,这取决于您将数组传递给子例程的方式。
猜你喜欢
  • 2014-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多