2017-01-19 16 views
1

私は全てのプロセッサに数字のあるリストrangeを持っています。私はこれらのリストのすべての行の最大数を決定したいrange。すべてのプロセッサP0-P3用MPI_Allreduceの効率的な使用

enter image description here

最初の4つのリストrange。赤いリストには、MPI_Allreduce以降の各プロセッサが取得する各行の最大値が含まれています。

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

//#define KEY_MAX 100 

typedef struct{ 
    int myrank; 
    int numprocs; 
    int *range; 
} SubDomainKeyTree; 

void compRange(SubDomainKeyTree *s, int myrank, int numprocs){ 
    s->myrank = myrank; 
    s->numprocs = numprocs; 

    // Allocate memory for (numprocs+1) ranges 
    s->range = malloc((numprocs+1) * sizeof(int)); 
    // Compute range values 
    for(int p=0; p<=numprocs; p++){ 
     s->range[p] = rand()%100; 
    } 

    for(int p=0; p<s->numprocs; p++){ 
     if(s->myrank == p){ 
     for(int k=0; k<=s->numprocs; k++){ 
      printf("Processor %d: %d random number is %d\n", p, k, s->range[k]); 
     } 
     printf("\n"); 
     } 
    } 
    } 

    void compDynRange(SubD *s){ 

     int rangeForAll[s->numprocs+1]; 
     ////////////////////////////////// 
     // This is not really efficient // 
     ////////////////////////////////// 
     for(int r=0; r<=s->numprocs; r++){ 
      MPI_Allreduce(&s->range[r], &rangeForAll[r], 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); 
     } 

    for(int p=0; p<s->numprocs; p++){ 
     if(s->myrank == p){ 
      for(int k=0; k<=s->numprocs; k++){ 
       s->range[k] = rangeForAll[k]; 
       printf("Processor %d: %d random number after MPI_Allreduce is %d\n", p, k, s->range[k]); 
      } 
      printf("\n"); 
     } 
    } 
} 

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

    int nameLen; 
    char processorName[MPI_MAX_PROCESSOR_NAME]; 

    int myrank;   // Rank of processor 
    int numprocs;   // Number of processes 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Get_processor_name(processorName,&nameLen); 
    MPI_Status status; 

    time_t t; 
    srand((unsigned)time(NULL)+myrank*numprocs+nameLen); 

    SubD s; 
    compRange(&s, myrank, numprocs); 

    compDynRange(&s); 
    MPI_Finalize(); 
    return 0; 
} 

は、私が使用してforループ私には非常に非効率です:ここで

は、私のコードの作業バージョンです。ここでは、すべてのリストのすべての行の最大値を順番に計算します。

しかし、forループなしでMPI_Allreduceを使用できますか?

for-loopの代わりにこれを試してみましたが、うまくいきません。

MPI_Allreduce(&s->range, &rangeForAll, s->numprocs+1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);

誰かが私に私はそれを行うことができますどのようにヒントを与えることはできますか?

+2

あなたは本当にあなたの質問に '&'のように使用しましたか?もしそうなら、 'MPI_Allreduce()'の呼び出しからそれらを削除してください。それだけで動作するはずです... – Gilles

+0

@Gilles Perfect!それは動作します! – Samuel

答えて

1

コメントで暗示されているように、コードでのエラーは、送信バッファと受信バッファを含む配列を渡すのではなく、ポインタを渡していたことです。私は、このエラーが、最初に使用された単一の要素(例えば&s->range[r])から、完全に正しい配列に、インデックスされたアクセス(すなわち&s->range)を間違って削除しただけで起こったと思います。だから、

説明したように、使用して:

MPI_Allreduce(s->range, rangeForAll, s->numprocs+1, MPI_INT, MPI_MAX, MPI_COMM_WORLD) 

はただのトリックを行います。しかし、結果はではなく、s->rangeの配列に格納したいので、あとで定義しない方が良いでしょう。キーワードを送信パラメータとして使用し、s->rangeを受け取るようにしてください。呼び出しは次のようになるバッファーの送受信の両方

MPI_Allreduce(MPI_IN_PLACE, s->range, s->numprocs+1, MPI_INT, MPI_MAX, MPI_COMM_WORLD) 

s->range作用します。したがって、最終結果はコール後にすべてs->rangeバッファ内にあるため、明示的にコピーを行う必要はありません。

関連する問題