2013-01-23 52 views
0

如果我用数组运行我的fortran程序(查看代码),我得到错误的计算值。如果我使用intel检查器(-mi3),它会告诉我每次在程序中使用一个大数组时,都会出现内存问题“无效的内存访问”,并且在/ lib64/ld-linux-x86- 64.so.2。 首先,我认为我没有足够的内存空间,但在具有16 GB内存的64位计算机上,有足够的内存空间(:free -m〜14 GB)。 如果我估计我的程序的内存大小,大约4 GB应该足够了。当我的程序正在运行时,已用内存从0%增加到〜20%,并停在那里,直到程序终止“正常”。所以我认为我有足够的内存空间。对于小型阵列(例如nemax = 3 000 000),我可以在intel检查器中获得正确的计算值并且无错误。我也用旗检查了所有数组。 我用ifort -mcmodel = medium -shared-intel -o test test.f90编译程序。 我不知道如何解决这些内存访问错误?有没有人有想法? 感谢您的帮助!无效的内存访问Fortran检查器

module lz_data 

    integer,parameter :: maxsite=16 
    integer,parameter :: nmax =6000000 
    integer,parameter :: nemax=300000000 

    real*8,save :: diag(nmax)   

    real*8,save :: werte(nemax)    !Here are the only large arrays 
    integer,save :: izeile(nemax) 
    integer,save :: ispalt(nemax) 

    integer,save :: nentry 

    end module lz_data 

    prgram test 
    use lz_data 

    implicit real*8 (a-h,o-z) 
    real*8 umat(maxsite,maxsite) 
    logical lav(nmax,maxsite) 
    logical lbv(nmax,maxsite) 

    ... 

    do is=1,ns 
    diag(is)=0.0d0 ! HERE the debugging tool says invalid memory access 
    do i=1,msite 
     do j=1,msite 
     if (lav(is,i).and.lbv(is,j)) diag(is)=diag(is)+umat(i,j) ! invalid memory access 
     enddo 
    enddo 
    enddo 
+5

您已明确使用隐式键入。然后,您将使用未声明和未初始化的变量,例如'is','ns'和'msite'来控制您的循环。如果你没有初始化'ns',那么'diag(is)'引用一个无效的内存位置就不足为奇了。并且请不要告诉我,您已经省略了这些变量的声明和初始化,调试其他人的代码很难,当我看到所有这些变量时,隐藏必要的行是非常糟糕的运动。 –

+0

感谢您的评论,但为什么我的变量未声明。如果我使用隐式实数* 8(a-h,o-z),所有以i-n开始的变量都是整数。 – user2003049

+0

与其将头发分为是否已声明,请告诉我们它们初始化的位置和值。 –

回答

1

看起来像是遇到了一些静态数组大小限制。 mcmodel = medium“应该”对此有所帮助,但显然不是。你可以用可分配数组替换你的大型静态数组,并看看是否有帮助。

哦,和高性能标记一样,使用隐式无,确保初始化所有变量,并提供自包含的示例代码。

+0

感谢您的帮助!我已经设置了ulimit -s无限制。 – user2003049

1

除了其他优秀的建议之外,我建议使用尽可能多的调试选项进行编译,包括运行时错误检查。编译器会向您发出有关可能导致错误并会发现其他错误的错误操作的警告。不好的做法包括未申报或未初始化的变量。我建议不要使用隐式键入和声明每个变量。通过运行时下标检查,编译器会告诉你何时下标超出了数组边界......这是一个比无效内存访问更容易理解的错误。采用Intel ifort尝试:-O2 -stand f03 -assume realloc_lhs -check all -traceback -warn all -fstack-protector -assume protect_parens -implicitnone

编辑的代码示例,这样它会通过这些选项执行的规则顺利地编译后运行提供错误消息:

forrtl: severe (193): Run-Time Check Failure. The variable '_test_$NS' is being used without being defined 

即ifort发现在未初始化变量运行。这导致程序运行到数组的末尾并访问无效内存。

1

除了其他建议之外,还应该确保在shell中没有默认的堆栈大小限制。通常在堆栈上创建静态数组,而BASH中的默认堆栈大小为8Mb。如果你的数组大于最终的访问冲突。您可以通过在BASH设置

ulimit -s unlimited 

,让您的堆栈大小只在您的系统中可用的内存限制覆盖此限制。

-2

感谢您的帮助!我已经设置了ulimit -s unlimited或10 GB。我知道使用隐式不是很好,但对于较小的系统,我的程序运行得非常好,为什么使用隐式会出现错误。我想使用可分配数组而不是大的静态数组,但在我的情况下,它没有任何意义,因为大数组werte的值的计算与数组的范围有关。所以我不得不浪费一点(!)的内存来预测我的静态数组的足够大小。预测维度在我的情况下并不复杂,我绝对(100%)确信计算的数组适合静态数组。我甚至用 - 检查所有标志来检查它。我可以用diag(nmax)数组创建一个可分配数组,所以我会检查这个,但是这个数组远远没有werte(nemax)数组那么大。

+0

使用隐式类型不一定是错误的,但它会使代码更难以遵循,并有产生棘手错误的风险。使用'implicit none'可以以非常小的成本提供巨大的好处,尤其是因为您明确声明了大部分变量的类型和种类。另外,你对可分配数组有什么异议?无论您的阵列的大小需要更改还是直到运行时间才知道,它们都很方便。 – sigma