1. MPI_Reduce函数

int MPI_Reduce(void *sendBuf, void *receiveBuf, int count, MPI_Datatype dataType, 

                               MPI_Op operator, int root, MPI_Comm comm)

每个进程从sendBuf向root进程的receiveBuf发数据,通过opration函数(例如MPI_SUM)来汇总数据。 

2. 图型示例

3. 举例

 

[cpp] view plaincopy
 
  1. #include<stdio.h>  
  2. #include"mpi.h"  
  3. #define SIZE 4  
  4.   
  5. int main(int argc, char *argv[]){  
  6.         int totalNumTasks, rankID;  
  7.   
  8.         float sendBuf[SIZE][SIZE] = {  
  9.                 {1.0,   2.0,    3.0,    4.0},  
  10.                 {5.0,   6.0,    7.0,    8.0},  
  11.                 {9.0,   10.0,   11.0,   12.0},  
  12.                 {13.0,  14.0,   15.0,   16.0}  
  13.         };  
  14.   
  15.         MPI_Init(&argc, &argv);  
  16.         MPI_Comm_rank(MPI_COMM_WORLD, &rankID);  
  17.         MPI_Comm_size(MPI_COMM_WORLD, &totalNumTasks);  
  18.   
  19.         float totalSum;  
  20.         if(totalNumTasks == SIZE){  
  21.                 int source = 0;  
  22.                 int sendCount = SIZE;  
  23.                 int recvCount = SIZE;  
  24.                 float recvBuf[SIZE];  
  25.                 //scatter data from source process to all processes in MPI_COMM_WORLD  
  26.                 MPI_Scatter(sendBuf, sendCount, MPI_FLOAT,   
  27.                             recvBuf, recvCount, MPI_FLOAT, source, MPI_COMM_WORLD);  
  28.   
  29.                 float sumPerProcess = recvBuf[0] + recvBuf[1] + recvBuf[2] + recvBuf[3];  
  30.                 printf("my rankID = %d, receive Results: %f %f %f %f, totalOnMe = %f\n",   
  31.                         rankID, recvBuf[0], recvBuf[1], recvBuf[2], recvBuf[3], sumPerProcess);  
  32.   
  33.                 int count = 1;  
  34.                 int root = 0;  
  35.                 MPI_Reduce(&sumPerProcess, &totalSum, count, MPI_FLOAT, MPI_SUM, root, MPI_COMM_WORLD);  
  36.                 printf("Process %d is done.\n", rankID);  
  37.                 fflush(stdout);  
  38.         }  
  39.         else  
  40.                 printf("Please specify -n %d\n", SIZE);  
  41.   
  42.         MPI_Finalize();  
  43.         if(rankID == 0) printf("totalSum = %f\n", totalSum);  
  44.         return 0;  
  45. }  

 

4. 编译执行

 

[plain] view plaincopy
 
  1. [amao@amao991 mpi-study]$ mpicc scatterReducer.c   
  2. [amao@amao991 mpi-study]$ mpiexec -n 4 -f machinefile ./a.out   
  3. my rankID = 0, receive Results: 1.000000 2.000000 3.000000 4.000000, totalOnMe = 10.000000  
  4. my rankID = 1, receive Results: 5.000000 6.000000 7.000000 8.000000, totalOnMe = 26.000000  
  5. Process 1 is done.  
  6. my rankID = 3, receive Results: 13.000000 14.000000 15.000000 16.000000, totalOnMe = 58.000000  
  7. Process 3 is done.  
  8. Process 0 is done.  
  9. my rankID = 2, receive Results: 9.000000 10.000000 11.000000 12.000000, totalOnMe = 42.000000  
  10. Process 2 is done.  
  11. totalSum = 136.000000  

 

5. 总结

(1)本例先通过MPI_Scatter函数把数组分发给4个进程(每个进程收到4个float值),每个进程对自己收到的4个数据求和

(2)然后通过MPI_Reduce函数汇总4个进程的数据,得到总和totalSum值。

(3)本例典型地说明了数据分发个多个进程/每个进程单独求解/然后汇总。

----------------------------------------------------------------

1. MPI_Gather函数

MPI_Gather (&sendbuf,sendcnt,sendtype,&recvbuf, recvcount,recvtype,root,comm) 

Gathers distinct messages from each task in the group to a single destination task. This routine is the reverse operation of MPI_Scatter. 

2. 图示

3. 举例

 

[cpp] view plaincopy
 
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include"mpi.h"  
  4.   
  5. int main(int argc, char *argv[]){  
  6.         int rankID, totalNumTasks;  
  7.   
  8.         MPI_Init(&argc, &argv);  
  9.         MPI_Barrier(MPI_COMM_WORLD);  
  10.         double elapsed_time = -MPI_Wtime();  
  11.   
  12.         MPI_Comm_rank(MPI_COMM_WORLD, &rankID);  
  13.         MPI_Comm_size(MPI_COMM_WORLD, &totalNumTasks);  
  14.   
  15.         int* gatherBuf = (int *)malloc(sizeof(int) * totalNumTasks);  
  16.         if(gatherBuf == NULL){  
  17.                 printf("malloc error!");  
  18.                 exit(-1);  
  19.                 MPI_Finalize();  
  20.         }  
  21.   
  22.         int sendBuf = rankID; //for each process, its rankID will be sent out  
  23.   
  24.         int sendCount = 1;  
  25.         int recvCount = 1;  
  26.         int root = 0;  
  27.         MPI_Gather(&sendBuf, sendCount, MPI_INT, gatherBuf, recvCount, MPI_INT, root, MPI_COMM_WORLD);  
  28.   
  29.         elapsed_time += MPI_Wtime();  
  30.         if(!rankID){  
  31.                 int i;  
  32.                 for(i = 0; i < totalNumTasks; i++){  
  33.                         printf("gatherBuf[%d] = %d, ", i, gatherBuf[i]);  
  34.                 }  
  35.                 putchar('\n');  
  36.                 printf("total elapsed time = %10.6f\n", elapsed_time);  
  37.         }  
  38.   
  39.         MPI_Finalize();  
  40.         return 0;  
  41. }  

 

4. 编译执行


 

[plain] view plaincopy
 
  1. [amao@amao991 mpi-study]$ mpicc gather.c  
  2. [amao@amao991 mpi-study]$ mpiexec -f machinefile -n 5 ./a.out  
  3. gatherBuf[0] = 0, gatherBuf[1] = 1, gatherBuf[2] = 2, gatherBuf[3] = 3, gatherBuf[4] = 4,  
  4. total elapsed time =   0.009653  

 

5. 总结

(1) 本例用了malloc在heap中开辟连续空间(数组)

int* gatherBuf = (int *)malloc(sizeof(int) * totalNumTasks);     而后用gatherBuf[i]的形式来逐个显示每个空间的值。

posted on 2012-04-22 12:23  前端小屁孩  阅读(473)  评论(0编辑  收藏  举报