1

本当に奇妙なことをしているMPIと並列化しているFortranコードがいくつかあります。まず、ボス プロセスからすべてのワーカーにブロードキャストする変数 nstartg があります。

call mpi_bcast(nstartg,1,mpi_integer,0,mpi_comm_world,ierr)

nstartgプログラム内で変数が再度変更されることはありません。後で、boss プロセスにeproc配列の要素をedgeワーカーに送信させます。

if (me==0) then
    do n=1,ntasks-1
        (determine the starting point estart and the number eproc
         of values to send)
        call mpi_send(edge(estart),eproc,mpi_integer,n,n,mpi_comm_world,ierr)
    enddo
endif

meゼロ以外の場合、一致する receive ステートメントを使用します。(読みやすくするために他のコードを省略しています。scatterv を使用しないのには十分な理由があります。)

ここで奇妙なことが起こります: 変数は実際の値を保持する代わりに にnstartg変更されます。nたとえば、プロセス 1 では、mpi_recv の後、nstartg = 1プロセス 2 では 2 に等しい、などです。さらに、上記のコードを次のように変更すると

call mpi_send(edge(estart),eproc,mpi_integer,n,n+1234567,mpi_comm_world,ierr)

それに応じてタグを mpi_recv への一致する呼び出しで変更し、プロセス 1 で nstartg = 1234568; プロセス 2 では、nstartg = 1234569 など。

一体何が起こっているのですか?変更したのは、mpi_send/recv がメッセージを識別するために使用しているタグだけです。メッセージが混同されないようにタグが一意である場合、これは何も変更しないはずですが、まったく無関係な変数を変更しています.

ボス プロセスでnstartgは は変更されていないので、再度ブロードキャストすることで修正できますが、それでは根本的な解決にはなりません。最後に、電気フェンスを使用してこのコードをコンパイルして実行しても、バッファ オーバーフローは検出されず、-fbounds-check で何もスローされませんでした。

4

1 に答える 1

5

最も可能性の高い原因は、定数として利用可能な実装固有のサイズを持つ配列として実際に宣言する必要があるときに、実際の引数INTEGERとしてスカラーを渡すことです。statusMPI_RECVMPI_STATUS_SIZE

INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status

また

INTEGER status(MPI_STATUS_SIZE)

メッセージ タグは、受信操作によってステータス フィールドの 1 つに書き込まれます (その実装固有のインデックスはMPI_TAG定数として使用でき、フィールド値は としてアクセスできます) status(MPI_TAG)。上書きされました。あなたの場合、スタックのすぐ上に落ちるように単純に起こります。statusINTEGERnstartgstatus

受信ステータスを気にしない場合は、MPI_STATUS_IGNORE代わりに特別な定数を渡すことができます。

于 2012-12-06T08:17:57.953 に答える