2017-06-23 17 views
0

ノンブロッキングMPI_IsendとブロックMPI_Sendを受信側でMPI_Irecvでブロックすることの間の時間差を測定しようとするコードがあります。 MPI_Waitallは、すべての要求ハンドラが起動された後にのみ時間が評価されるようにするために使用されています。私は、コードを実行したときしかし、私が取得:MPI_Waitall無効なリクエスト

[user:30439] *** An error occurred in MPI_Waitall 
[user:30439] *** reported by process [931725313,1] 
[user:30439] *** on communicator MPI_COMM_WORLD 
[user:30439] *** MPI_ERR_REQUEST: invalid request 
[user:30439] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort, 
[user:30439] *** and potentially your MPI job) 

関連の答えは、ほとんどが、おそらく関数呼び出しとコードのMPI_Waitallの配置内部の引数にエラーを指します。両方私はここで識別し、修正することに失敗した。事前に

#include "mpi.h" 
#include <stdio.h> 
#include <stdlib.h> 

#define COMM MPI_COMM_WORLD 
#define REPS 1000 
#define DISP 100 

int main (int argc, char *argv[]) 
{ 
int numtasks, rank, buf, tag1=1, i, rc, dest, src, offset, nreqs; 
double T1, T2; 
MPI_Request reqs[REPS*2]; 
MPI_Status stats[REPS*2]; 

MPI_Init(&argc,&argv); 
MPI_Comm_size(COMM, &numtasks); 
MPI_Comm_rank(COMM, &rank); 

/* Require 4 tasks */ 
if (rank == 0) { 
    if (numtasks != 4) { 
    printf("ERROR: Number of tasks must be 4. Quitting.\n"); 
    MPI_Abort(COMM, rc); 
    } 
    printf("Starting isend/irecv send/irecv test...\n"); 
    } 

/* Use barriers for clean output */ 
MPI_Barrier(COMM); 
printf("Task %d starting...\n", rank); 
MPI_Barrier(COMM); 

T1 = MPI_Wtime();  /* start the clock */ 

/* Tasks 0 and 1 do the isend/irecv test. 
* Determine who to send/receive with. nreqs specifies how many non-blocking 
* operation request handles to capture. offset is where the task should 
* store each request as it is captured in the reqs() array.   */ 
if (rank < 2) { 
    nreqs = REPS*2; 
    if (rank == 0) { 
    src = 1; 
    offset = 0; 
    } 
    if (rank == 1) { 
    src = 0; 
    offset = REPS; 
    } 
    dest = src; 

/* Do the non-blocking send and receive operations */ 
    for (i=0; i<REPS; i++) { 
    MPI_Isend(&rank, 1, MPI_INT, dest, tag1, COMM, &reqs[offset]); 
    MPI_Irecv(&buf, 1, MPI_INT, src, tag1, COMM, &reqs[offset+1]); 
    offset += 2; 
    if ((i+1)%DISP == 0) 
     printf("Task %d has done %d isends/irecvs\n", rank, i+1); 
    } 
    } 

/* Tasks 2 and 3 do the send/irecv test. 
    Determine who to send/receive with. nreqs specifies how many non-blocking 
    operation request handles to capture. offset is where the task should 
    store each request as it is captured in the reqs() array. */ 
if (rank > 1) { 
    nreqs = REPS; 

/* Task 2 does the blocking send operation */ 
    if (rank == 2) { 
    dest = 3; 
    for (i=0; i<REPS; i++) { 
     MPI_Send(&rank, 1, MPI_INT, dest, tag1, COMM); 
     if ((i+1)%DISP == 0) 
     printf("Task %d has done %d sends\n", rank, i+1); 
     } 
    } 

/* Task 3 does the non-blocking receive operation */ 
    if (rank == 3) { 
    src = 2; 
    offset = 0; 
    for (i=0; i<REPS; i++) { 
     MPI_Irecv(&buf, 1, MPI_INT, src, tag1, COMM, &reqs[offset]); 
     offset += 1; 
     if ((i+1)%DISP == 0) 
     printf("Task %d has done %d irecvs\n", rank, i+1); 
     } 
    } 

    } 

/* Wait for all non-blocking operations to complete and record time */ 
MPI_Waitall(nreqs, reqs, stats); 
T2 = MPI_Wtime();  /* end time */ 
MPI_Barrier(COMM); 

printf("Task %d time(wall)= %lf sec\n", rank, T2-T1); 

MPI_Finalize(); 
} 

ありがとう:

は、ここに私の完全なコードです。

答えて

2

コードに少なくとも3つの重大な問題があります。

  1. MPI_Irecvへの定期的な呼び出しに同じバッファを指定します。要求が完了する前に、非同期MPI関数に与えられたメモリに決して触れてはいけません。
  2. ランク2にはリクエストがありませんが、REPSリクエストがあると主張して、MPI_Waitallを呼び出します。
  3. ランク1はから2*REPS-1に書き込みを開始します。意味がありません。

全体的には、コードの書式と構造を改善して、これらの事柄について推論しやすくするよう努めなければなりません。また、MUSTをMPIの正しさチェックに使用すると、非常に役に立ちます。

関連する問題