2013-01-23 28 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