誰かが説明を提供できるかどうか疑問に思っています。私は、コードから始めましょう異常なMPIの振舞い
:行動
コード予想
/*
Barrier implemented using tournament-style coding
*/
// Constraints: Number of processes must be a power of 2, e.g.
// 2,4,8,16,32,64,128,etc.
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>
void mybarrier(MPI_Comm);
// global debug bool
int verbose = 1;
int main(int argc, char * argv[]) {
int rank;
int size;
int i;
int sum = 0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int check = size;
// check to make sure the number of processes is a power of 2
if (rank == 0){
while(check > 1){
if (check % 2 == 0){
check /= 2;
} else {
printf("ERROR: The number of processes must be a power of 2!\n");
MPI_Abort(MPI_COMM_WORLD, 1);
return 1;
}
}
}
// simple task, with barrier in the middle
for (i = 0; i < 500; i++){
sum ++;
}
mybarrier(MPI_COMM_WORLD);
for (i = 0; i < 500; i++){
sum ++;
}
if (verbose){
printf("process %d arrived at finalize\n", rank);
}
MPI_Finalize();
return 0;
}
void mybarrier(MPI_Comm comm){
// MPI variables
int rank;
int size;
int * data;
MPI_Status * status;
// Loop variables
int i;
int a;
int skip;
int complete = 0;
int currentCycle = 1;
// Initialize MPI vars
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
// step 1, gathering
while (!complete){
skip = currentCycle * 2;
// if currentCycle divides rank evenly, then it is a target
if ((rank % currentCycle) == 0){
// if skip divides rank evenly, then it needs to receive
if ((rank % skip) == 0){
MPI_Recv(data, 0, MPI_INT, rank + currentCycle, 99, comm, status);
if (verbose){
printf("1: %d from %d\n", rank, rank + currentCycle);
}
// otherwise, it needs to send. Once sent, the process is done
} else {
if (verbose){
printf("1: %d to %d\n", rank, rank - currentCycle);
}
MPI_Send(data, 0, MPI_INT, rank - currentCycle, 99, comm);
complete = 1;
}
}
currentCycle *= 2;
// main process will never send, so this code will allow it to complete
if (currentCycle >= size){
complete = 1;
}
}
complete = 0;
currentCycle = size/2;
// step 2, scattering
while (!complete){
// if currentCycle is 1, then this is the last loop
if (currentCycle == 1){
complete = 1;
}
skip = currentCycle * 2;
// if currentCycle divides rank evenly then it is a target
if ((rank % currentCycle) == 0){
// if skip divides rank evenly, then it needs to send
if ((rank % skip) == 0){
if (verbose){
printf("2: %d to %d\n", rank, rank + currentCycle);
}
MPI_Send(data, 0, MPI_INT, rank + currentCycle, 99, comm);
// otherwise, it needs to receive
} else {
if (verbose){
printf("2: %d waiting for %d\n", rank, rank - currentCycle);
}
MPI_Recv(data, 0, MPI_INT, rank - currentCycle, 99, comm, status);
if (verbose){
printf("2: %d from %d\n", rank, rank - currentCycle);
}
}
}
currentCycle /= 2;
}
}
は、ブロッキングMPI_Send関数とMPI_RECV呼び出しを使用してそのポイントに到達するために他のすべてのプロセスを待ち、500に合計をインクリメントすることです、その後、
予想どおりにクラスターにクラスタの動作1000
観察された挙動に合計をインクリメント
異常行動私のマシン
に観察主な機能のすべてのプロセスは、私は、具体的mybarrierの第二のwhileループのタグにリンクされている99、であると報告されています。
加え
で私の最初のドラフトは、forループで書かれた、とだけでなく、クラスタ上で予想されるように、その1で、プログラムが実行されますが、私のマシンの実行にすべてのプロセスがMPI_Finalize(呼び出しにもかかわらず、終了したことがありませんしかし、それを超えて動くものはありません)。
MPIのバージョン
私のマシンは、私は私のマシンが突然のすべてを実行するように見えることを観察した
クラスタがOpenRTE 1.6.3
質問を実行しているOpenRTE 2.0.2 を実行していますクラスタは正常に実行されます。これは私が書いた他のMPIコードにも当てはまります。私が気づいていない1.6.3と2.0.2の間に大きな変更がありましたか?
いずれにせよ、私は困惑しています。なぜ私のマシンがMPIを正しく実行していないように見えるのか誰かが説明できるかどうか疑問に思っていました。十分な詳細を提供していただければ幸いですが、必要でない場合は、必要な追加情報を提供いたします。
私はそれを修正したと信じています。ご協力いただきありがとうございます。私はMPIを初めて使っているので、私はまだすべてがどのように機能するか把握しようとしています。 – electr0sheep