2013-04-22 15 views
6

私は次のような状況に陥りました。私のコードで送信と受信のどちらの組み合わせが最適であるかを調べるために、いくつかの短いMPIテストコードを書いています。C++:奇妙なポインタの破損エラー

コードは自分のコンピュータ(8つのプロセスでテスト済み)で完璧に動作しますが、作業しているクラスタを実行するとすぐに、破損しているか、これは出力です:http://pastebin.com/pXTRSf89

私のコードで何をしているのですか:私は私の通信機能を100K回呼び出して時間を測定します。この機能を以下に示します。私が知ったことは、エラーは常に同じ繰り返し(6K程度のどこか)で起こるということです。ただし、報告されたプロセッサIDは変更されます。問題は次のとおりです。ポインタが解放または割り当てられていないので、私は間違いがあり、何が間違っているのかもしれません。

void communicateGrid(int level, real* grid, const Subdomain& subdomain, std::vector<TimeMap>& tm_) { 
    tm_[level]["CommGrid"].start(); 

    MPI_Status status[2]; 
    MPI_Request request[2]; 

    // x 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1) + innerGridpoints_[level][0] - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 0, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1)], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 1, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndexInner(level, 1,1,1) + innerGridpoints_[level][0]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 1, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(&grid[getIndexInner(level, 1,1,1) - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 0, MPI_COMM_WORLD, &status[1]); 

    //y 
    MPI_Isend(&grid[getIndex(level, 0, innerGridpoints_[level][1], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 2, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 3, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, innerGridpoints_[level][1] + numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 3, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 2, MPI_COMM_WORLD, &status[1]); 

    // z 
    MPI_Isend(&grid[getIndex(level, 0, 0, innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 4, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level])], 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 5, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level] + innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 5, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 4, MPI_COMM_WORLD, &status[1]); 

    tm_[level]["CommGrid"].stop(); 
} 

mpiTypes_はタイプMPI_Datatype *、innerGridpoints_とnumOuterGridpoints_のグローバル変数であるだけでなく(私はこれは良いコーディングスタイルではないことを知っているが、私はタイミングだけのためにそれを取った)グローバルです。 コミュニケーション機能の別の設定(例:Irecvに続いて送信)で動作するため、自分のデータ型が正しいことは間違いありません。

最終的な注意:私はちょうど1つのプロセスでこれを実行しようとしました。その後、次のエラーが発生しました:

ランク0月4月22日2時11分23秒2013] [c0-0c1s3n0] PMPI_Isendで致命的なエラー:内部MPIエラー!エラー・スタック:PMPI_Isend(148): 内部MPIエラー!MPI_Isend(buf = 0x2aaaab7b531c、count = 1、dtype = USER、dest = 0、 タグ= 1、MPI_COMM_WORLD、request = 0x7fffffffb4d4) _pmiu_daemon(SIGCHLD):

を中止[NID 00070] [c0-0c1s3n0] [月4月22日午前2時11分23秒2013] PEのRANK 0終了信号再び、これはクラスタで起こったが、上で働い私のマシン。

私は何かをチェックすることができますか、どこでエラーが発生する可能性があります! ありがとう

+0

どのブランドのCPUが動作し、どのブランドのCPUが故障しますか? – Patashu

+0

あなたのポインタが、決して捨ててはならないデータのブロックを指しているかどうかは疑問です。あなたが '&grid [getIndex(level、0、0、numOuterGridpoints_ [level] + innerGridpoints_ [level] [2])]'のようなことをすると、あなたのものではないブロックを指す可能性はありますか?または、呼び出している関数にメモリリークがある可能性があります...両方のマシンでコンパイラ/ライブラリとまったく同じバージョンですか? – Floris

+0

getIndexとgetInnerIndexは、グリッドが3次元配列であるため、インライン化されたインデックス関数です。私のPCはgcc 4.6.0(Macシステム)でコンパイルされたIntel i5で、クラスタはOpteron CPUを搭載したCrayマシンです。私はgcc(version 4.6.3)と同様に標準のPGIコンパイラを試しました – Chris

答えて

2

MPI_Isend()で作成されたMPIリクエストで何かを試してみると、内部リソースがリークしてしまい、結局クラッシュすることがあります。

Jeff Squyresは彼のblog post at Ciscoに非常によく似ています。

あなたはそれらのIsendsが完了しているが、MPIライブラリはこれを知り、割り当てられたリソースをクリーンアップする方法がありませんし、それらのMPI_Request sが指すことを知っている。必要なリソースの量と種類は、基盤となるネットワーク接続(例えば、希少なインフィニバンドリソースを奪取する可能性があります)を含む多くのものによって決まります。したがって、自分のマシンでは動作しますがクラスタでは動作しないことは必ずしも驚くことではありません。

あなたはMPI_Isend/MPI_Recv()秒の各段階の後

MPI_Waitall(2, request, status); 

を追加することによってこの問題を解決することができます。

リソースのクリーンアップに必要なだけでなく、非ブロッキング要求のあるプログラムの正確さのために実際に必要です。

+0

確かに、今、それは、ありがとう、働いています。これが必要であることを決して知らなかった、私はいつもあなたがすべてが正しく受け取られることを知っていればあなたが待ち時間を避けることができると思った – Chris