1

MPI_FINALIZE()Fortran90プログラムでの呼び出し中にセグメンテーション違反が発生します。コードは非常に広範囲ですが、擬似コードを投稿して、フラグが発生するかどうかを確認します。配列の割り当てを解除しないことが原因である可能性があるという予感があります(ただし、まだこれを試していません) 。ただし、よくわかりません。Fortran90で配列の割り当てを解除できないと、呼び出し中にセグメンテーション違反が発生する可能性がありMPI_FINALIZEますか?

if(<rank 0>) then
  do iat = 1,natoms
    do il = 0, LMAX
      do im = -il,il
        <mpi_recv "rank_rdy"> ! find out which rank is ready for (at,l,m)
        <mpi_send "(iat,il,im)"> ! send (at,l,m) to the rank asking for it
      enddo
    enddo
  enddo
else ! other ranks send a 'ready' signal and recieve the (at,l,m) to optimize
  if(<rank 0 is not finished processing (at,l,m)'s>)
    <mpi_send "my_rank"> ! tell rank 0 that i am ready to receive
    <mpi_recv "(iat,il,im)"> ! recieve (at,l,m) from rank 0
    call optimize(iat,il,im) ! do work on (at,l,m)
  endif
endif

if(<rank 0>)
  <read temp files created by other ranks>
  <write temp files to one master file>
endif

print*, 'calling finalize'

call MPI_BARRIER(MPI_COMM_WORLD, ierr)
call MPI_FINALIZE()

出力時に、この問題に関係のない他の情報の中でも、次の情報が得られます。

 calling finalize
 calling finalize
 calling finalize
 calling finalize
 calling finalize
 calling finalize

=====================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 11
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
=====================================================================================
APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)

電話をかけなくても同じ問題が発生しますMPI_BARRIERが、それが役立つかもしれないと思いました。すべてのランクで使用されている配列がありますが、プログラム全体で使用しているため、メモリリークなどの心配がないため、割り当てを解除する必要はありません。MPI_FINALIZE()メモリを解放せずに呼び出されたために、このセグメンテーション違反が発生している可能性はありますか?

私はこれを自分でもっと探求するつもりですが、いくつかの理由でこの質問を投稿したいと思いました:

  1. 電話をかけるときにこれが既知の問題であるかどうかを知りたいMPI_FINALIZE()

  2. を呼び出すときに、なぜこれが発生するのか(実際に問題がある場合)を知りたいMPI_FINALIZE()。内部的には、このセグメンテーション違反の原因は何ですか?

  3. 私はオンラインで高低を検索しましたが、この問題については何も見つかりませんでした。したがって、後世のために、これはWebで答えるのに良い質問かもしれません。

編集:これについて言及するのを忘れましたが、シリアルで実行するとこの問題を再現できません。(at,l,m)もちろん、私はシリアルでの配布はしていません。唯一のプロセスは、すべての組み合わせを実行し、それらを1つずつ最適化するだけです。ただし、MPIで問題を引き起こしている可能性があると思われるアレイの割り当てを解除しません。それでも、セグメンテーション違反は発生しません

4

1 に答える 1

5

古いFORTRAN77インターフェースの代わりに、可能な場合は常にFortran90MPIインターフェースを使用する必要があります。つまり、あなたは常にすべきです

USE mpi

それ以外の

INCLUDE 'mpif.h'

2つの違いは、Fortran 90インターフェースがすべてのMPIサブルーチンをモジュールに配置するため、明示的なインターフェースが生成されることです。これにより、コンパイラは呼び出しで引数チェックを実行し、たとえば引数を省略した場合にエラーを通知できます。

Fortranの呼び出し規約では、すべての引数は、タイプに関係なく、アドレスによって渡されます。これにより、コンパイラーはCのようにプロトタイプを必要とせずに、関数とサブルーチンへの適切な呼び出しを生成できます。ただし、これはINTEGER、の配列REALが期待される引数を自由に渡すことができ、事実上すべてのFORTRAN77コンパイラーがそのようなコードまたは1つを喜んでコンパイルすることを意味します。予想よりも少ない/多い引数を渡すことができます。ソースツリー全体を解析し、コンパイラが見つけようとしないエラーやその他の多くのエラーを特定できる、通常はCツールの名前でリンターと呼ばれる外部ツールがあります。lintFortranのそのような静的コード分析を行うそのようなツールの1つはflint。Fortran 90は、Fortranのこのエラーが発生しやすい性質を補うために、インターフェースを追加しました。

予想よりも少ない引数でFortranサブルーチンを呼び出すと、アーキテクチャーによってさまざまな悪影響が生じる可能性がありますが、ほとんどの場合、特に省略された引数が出力引数である場合は、クラッシュが発生します。呼び出された関数は、渡される引数が少ないことを認識していません。アドレスがどこにあるべきかを調べ、そこで見つかったアドレスを取得します。としてierrは出力引数であり、そのアドレスで書き込みが発生します。アドレスがマップされたメモリに対応する仮想アドレスを指しておらず、OSによって大量のセグメンテーション違反が発生する可能性があります。アドレスがユーザーに割り当てられたメモリのどこかを指している場合でも、結果として、一部の制御構造の重要な値が上書きされる可能性があります。それでも起こらない場合は、呼び出し先がスタックフレームをクリーンアップする呼び出し規約があります。この場合、スタックポインターが誤ってインクリメントされ、リターンアドレスが正しいアドレスとは完全に異なります。確かに、実行不可能な(さらにはマップされていない)メモリにジャンプし、再びセグメンテーション違反につながります。

于 2012-07-19T19:31:58.117 に答える