0

配列を使用して fortran プログラムを実行すると、間違った計算値が得られます (コードを見てください)。intel インスペクタ (-mi3) を使用すると、プログラムで大きな配列の 1 つが使用されるたびに「無効なメモリ アクセス」というメモリの問題が発生し、/lib64/ld-linux-x86- にもエラーが発生することがわかります。 64.so.2. まず、十分なメモリ容量がないと思っていましたが、16 GB のメモリを搭載した 64 ビット マシンには十分なメモリ容量があります (:free -m ~14 GB)。プログラムのメモリ サイズを見積もると、約 4 GB で十分なはずです。プログラムの実行中に、使用メモリが 0% から ~20% に増加し、プログラムが「正常に」終了するまでそこで停止します。だから私は十分なメモリスペースを持っていると思います。小さな配列 (例: nemax=3 000 000) の場合、正しい計算値が得られ、intel インスペクターでエラーは発生しません。また、フラグ check all を使用して配列をチェックしました。プログラムを ifort -mcmodel=medium -shared-intel -o test test.f90 でコンパイルします。これらのメモリアクセスエラーを解決するために他に何ができるでしょうか? 誰かアイデアはありますか?? ご協力いただきありがとうございます!

  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
4

4 に答える 4

1

静的配列のサイズ制限に直面しているようです。mcmodel=medium はそれを助ける「はず」ですが、明らかにそうではありません。大きな静的配列を割り当て可能な配列に置き換えて、それが役立つかどうかを確認できます。

ああ、High Performane Mark が言ったように、暗黙的な none を使用し、すべての変数を必ず初期化し、自己完結型のサンプル コードを提供してください。

于 2013-01-23T11:02:51.567 に答える
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 は実行時に初期化されていない変数を見つけます。これにより、プログラムが配列の最後で実行され、無効なメモリにアクセスしていました。

于 2013-01-23T11:37:36.663 に答える
1

他のアドバイスに加えて、シェルのデフォルトのスタック サイズ制限に達していないことも確認する必要があります。通常、静的配列はスタック上に作成され、BASH のデフォルトのスタック サイズは 8Mb です。それより大きい配列がある場合、アクセス違反が発生します。設定することで、この制限をオーバーライドできます

ulimit -s unlimited

これにより、スタック サイズはシステムで使用可能なメモリによってのみ制限されます。

于 2013-01-23T12:34:22.087 に答える
-2

ご協力いただきありがとうございます!すでに ulimit -s 無制限または 10 GB を設定しています。暗黙の使用があまり良くないことは知っていますが、小規模なシステムではプログラムがまったく問題なく実行されるため、暗黙の使用でエラーが発生するのはなぜですか。大きな静的配列の代わりに割り当て可能な配列を使用したいのですが、大きな配列の値の計算が配列の範囲にリンクされているため、私の場合は意味がありません。そのため、静的配列の十分な次元を予測するために、少し (!) メモリを浪費する必要があります。私の場合、次元の予測は複雑ではなく、計算された配列が静的配列に収まることを絶対に (100%) 確信しています。-check all フラグでチェックしました。diag(nmax) 配列で割り当て可能な配列を作成できるので、これを確認します。

于 2013-01-25T10:39:59.703 に答える