2016-12-09 12 views
1

私はMPIを使ってこれを行うために行列を合計しようとしましたが、理由はわかりませんがMPI_Sendを使ってデータを送信できませんでしたここでC++ MPI:何も送信できませんでした

Sending 3 rows to task 1 offset=0 
Sending 3 rows to task 2 offset=3 
Sending 2 rows to task 3 offset=6 
Sending 2 rows to task 4 offset=8 
*** An error occurred in MPI_Send 
*** reported by process [1047527425,0] 
*** on communicator MPI_COMM_WORLD 
*** MPI_ERR_RANK: invalid rank 
*** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort, 
*** and potentially your MPI job) 

私のコードです:

# include <mpi.h> 
# include <stdio.h> 
# include <stdlib.h> 
# include <time.h> 
# include <vector> 

#define ROWS 10 
#define COLONS 10 
#define MASTER 0 

using namespace std; 

int main(int argc, char *argv[]) { 

    int rows; 

    int averow=0; 
    int extra=0; 
    int offset; 
    int numprocs; 
    MPI_Status status; 
    int matrixA[ROWS][COLONS]; 
    int matrixB[ROWS][COLONS]; 
    int matrixC[ROWS][COLONS]; 

    for (int i = 0; i < COLONS; i++) { 
     for (int j = 0; j < ROWS; j++) { 
      matrixA[i][j] = rand() % 10; 
      matrixB[i][j] = rand() % 10; 
     } 
    } 
    int my_id; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_id); 
    if (my_id == MASTER) { 

     averow = ROWS/numprocs; 
     extra = ROWS % numprocs; 
     offset = 0; 

     /* Send matrix data to the worker tasks */ 
     for (int dest = 1; dest <= numprocs; dest++) { 
      rows = (dest <= extra) ? averow + 1 : averow; 
      printf("Sending %d rows to task %d offset=%d\n", rows, dest, offset); 
      MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); 
      MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); 
      MPI_Send(&matrixA[offset][0], rows * ROWS, MPI_DOUBLE, dest, 1, 
      MPI_COMM_WORLD); 
      MPI_Send(&matrixB, COLONS * COLONS, MPI_INT, dest, 1, 
      MPI_COMM_WORLD); 
      offset = offset + rows; 
     } 

     /* Receive results from worker tasks */ 
     for (int i = 1; i <= numprocs; i++) { 
      int source = i; 
      MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); 
      MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); 
      MPI_Recv(&matrixC[offset][0], rows * COLONS, MPI_INT, source, 2, 
      MPI_COMM_WORLD, &status); 
      printf("Received results from task %d\n", source); 
     } 
    } 

    if (my_id != MASTER) { 
     MPI_Recv(&offset, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&rows, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&matrixA, rows * COLONS, MPI_DOUBLE, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&matrixB, COLONS * COLONS, MPI_DOUBLE, MASTER, 1, 
     MPI_COMM_WORLD, &status); 

     for (int k = 0; k < COLONS; k++) { 
      for (int i = 0; i < rows; i++) { 
       matrixC[k][i] = matrixA[k][i] + matrixB[k][i]; 
      } 
     } 
     MPI_Send(&offset, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD); 
     MPI_Send(&rows, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD); 
     MPI_Send(&matrixC, rows * COLONS, MPI_DOUBLE, MASTER, 2, 
     MPI_COMM_WORLD); 
    } 
    MPI_Finalize(); 

    return 0; 
} 

私は8つのプロセスでこのプログラムを実行していますが、私は、エラーメッセージが表示されますか。

ここで私が間違っていることを知っていますか?私は何も見ることができないので。

+2

CとC++の両方の質問にタグを付けることは、ほとんどの場合不適切です。これはC++プログラムです - それは私には些細な変更を伴うCプログラムである可能性がありますが、Cタグを削除しました。 – zwol

+2

ちなみに、このプログラムでは 'COLONS'は' COLUMNS'でなければなりません。 – zwol

+0

ところで、私は問題を確認します。エラーメッセージの前に、プログラムが何を出力するのかを編集しました。これは、 'MPI_Send'への最初の呼び出しでエラーが発生しないことを示しています。 – zwol

答えて

1

あなたのコードで間違った複数のものがあります。destiため

  1. ループは< numprocsでなければなりません。それ以外の場合は、コードが存在しないランク8に送信しようとしています!
  2. doubleデータがないのに、MPI_DOUBLEデータ型を使用していることがあります。 MPI_INTを送信し、MPI_DOUBLEを受信して​​も動作しません。
  3. MPI_Send(&matrixA[offset][0], rows * ROWS, ...は、rows * COLONSである必要があります。
  4. MPI_Send(&matrixB, COLONS * COLONS, ...は、ROWS * COLONSでなければならず、対応するMPI_Recvでもあるはずです。
  5. matrixAのチャンクを送信しながら、matrixB全体を転送することは、加算を計算する観点からも意味がありません。
  6. 行列の最初の次元はであり、2番目の行列はクームです。しかし、あなたの追加ループはこれを誤って組み合わせてしまいます。
  7. rowsおよびoffsetワーカータスクの結果を受信は正しく設定されていません。私はすべての実際のエラーをキャッチわからない

、大幅に改善することができるいくつかの側面もあります。

  1. 異なる意味を持つ定数ROWSと変数rowsを持つことは非常にに減算されますコードを簡単に理解する。
  2. あなたの通信設定は、不必要に複雑です。多くの場所でパターンを単純化することができます。それを送信する代わりにローカルでrowsoffsetを計算します。しかし、最も重要なのは、集合的な操作を使うべきです。これは、どちらの理由でも簡単に実行でき、さらに優れたパフォーマンスを発揮します。
  3. MPIでは、通常、マスターランクが計算に参加します。

落胆しないでください。初心者がMPIを理解することは難しいかもしれませんし、集団で簡単に行うことができる(間違って非効率的な)パターンを作ることは非常に一般的です。私の推薦は:

  1. まず始めに、あなたの現在の試みを破棄してください。
  2. MPI_ScattervMPI_Gathervについて学んでください。これらは、あなたの例で必要な唯一の通信機能です。また、マスターのコードパスの周りに別々のコードパスを設ける必要もありません。
  3. データレイアウトについて考えてみましょう。各ランクの行列の形は何ですか?グローバルマトリックスはどのようにローカルマトリックスにマップされますか?
  4. 意味を明白にかつ簡潔に説明する変数名を使用してください。
  5. コードを少しずつ書き、すべての行とパラメータについて注意深く考えてください。
  6. 動作する場合はCode Reviewに投稿してください。それが動作しない場合、またはあなたが立ち往生している場合は、新しい質問を投稿するか、またはこれを更新してください。どちらの場合も、ここにコメントを投稿してください。
関連する問題