2017-01-19 37 views
1

我在每個處理器上都有一個包含數字的列表range。我想確定這些列表的每一行的最大數量rangeMPI_Allreduce的高​​效使用

enter image description here

前四個列表range每處理器P0-P3。紅色列表包含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循環,這似乎非常低效給我。我在這裏計算所有列表中每行的最大值。

但是我可以使用MPI_Allreduce沒有for循環?

我已經試過,而不是沒有工作的for循環。

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

有人可以給我一個提示,我該怎麼辦呢?

+2

你真的在你的問題中使用了'&'嗎?如果是這樣,只需將它們從調用到'MPI_Allreduce()',並且應該只是工作... – Gilles

+0

@Gilles完美!這樣可行! – Samuel

回答

1

正如已經暗示的評論,你在代碼中的錯誤是,而不是傳遞包含你的發送和接收緩衝區的數組,你傳遞給他們一些指針。我想,這個錯誤只是簡單地從最初使用的單個元素(如&s->range[r])(這是完全正確的)轉換爲全部數組,通過刪除索引訪問(即&s->range)這是錯誤的。

因此,作爲解釋,使用:

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

只是做的伎倆。但是,由於您想將結果存入s->range陣列而不是臨時rangeFarAll,所以最好不要定義後者,並使用MPI_IN_PLACE關鍵字作爲發送參數,使用s->range作爲接收關鍵字。該呼叫變爲:

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

s->range既充當發送和接收緩衝區。因此,最後的結果將全部在調用後的s->range緩衝區中,從而不需要明確地進行復制。