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. 举例
- #include<stdio.h>
- #include"mpi.h"
- #define SIZE 4
-
- int main(int argc, char *argv[]){
- int totalNumTasks, rankID;
-
- float sendBuf[SIZE][SIZE] = {
- {1.0, 2.0, 3.0, 4.0},
- {5.0, 6.0, 7.0, 8.0},
- {9.0, 10.0, 11.0, 12.0},
- {13.0, 14.0, 15.0, 16.0}
- };
-
- MPI_Init(&argc, &argv);
- MPI_Comm_rank(MPI_COMM_WORLD, &rankID);
- MPI_Comm_size(MPI_COMM_WORLD, &totalNumTasks);
-
- float totalSum;
- if(totalNumTasks == SIZE){
- int source = 0;
- int sendCount = SIZE;
- int recvCount = SIZE;
- float recvBuf[SIZE];
-
- MPI_Scatter(sendBuf, sendCount, MPI_FLOAT,
- recvBuf, recvCount, MPI_FLOAT, source, MPI_COMM_WORLD);
-
- float sumPerProcess = recvBuf[0] + recvBuf[1] + recvBuf[2] + recvBuf[3];
- printf("my rankID = %d, receive Results: %f %f %f %f, totalOnMe = %f\n",
- rankID, recvBuf[0], recvBuf[1], recvBuf[2], recvBuf[3], sumPerProcess);
-
- int count = 1;
- int root = 0;
- MPI_Reduce(&sumPerProcess, &totalSum, count, MPI_FLOAT, MPI_SUM, root, MPI_COMM_WORLD);
- printf("Process %d is done.\n", rankID);
- fflush(stdout);
- }
- else
- printf("Please specify -n %d\n", SIZE);
-
- MPI_Finalize();
- if(rankID == 0) printf("totalSum = %f\n", totalSum);
- return 0;
- }
4. 编译执行
- [amao@amao991 mpi-study]$ mpicc scatterReducer.c
- [amao@amao991 mpi-study]$ mpiexec -n 4 -f machinefile ./a.out
- my rankID = 0, receive Results: 1.000000 2.000000 3.000000 4.000000, totalOnMe = 10.000000
- my rankID = 1, receive Results: 5.000000 6.000000 7.000000 8.000000, totalOnMe = 26.000000
- Process 1 is done.
- my rankID = 3, receive Results: 13.000000 14.000000 15.000000 16.000000, totalOnMe = 58.000000
- Process 3 is done.
- Process 0 is done.
- my rankID = 2, receive Results: 9.000000 10.000000 11.000000 12.000000, totalOnMe = 42.000000
- Process 2 is done.
- 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. 举例
- #include<stdio.h>
- #include<stdlib.h>
- #include"mpi.h"
-
- int main(int argc, char *argv[]){
- int rankID, totalNumTasks;
-
- MPI_Init(&argc, &argv);
- MPI_Barrier(MPI_COMM_WORLD);
- double elapsed_time = -MPI_Wtime();
-
- MPI_Comm_rank(MPI_COMM_WORLD, &rankID);
- MPI_Comm_size(MPI_COMM_WORLD, &totalNumTasks);
-
- int* gatherBuf = (int *)malloc(sizeof(int) * totalNumTasks);
- if(gatherBuf == NULL){
- printf("malloc error!");
- exit(-1);
- MPI_Finalize();
- }
-
- int sendBuf = rankID;
-
- int sendCount = 1;
- int recvCount = 1;
- int root = 0;
- MPI_Gather(&sendBuf, sendCount, MPI_INT, gatherBuf, recvCount, MPI_INT, root, MPI_COMM_WORLD);
-
- elapsed_time += MPI_Wtime();
- if(!rankID){
- int i;
- for(i = 0; i < totalNumTasks; i++){
- printf("gatherBuf[%d] = %d, ", i, gatherBuf[i]);
- }
- putchar('\n');
- printf("total elapsed time = %10.6f\n", elapsed_time);
- }
-
- MPI_Finalize();
- return 0;
- }
4. 编译执行
- [amao@amao991 mpi-study]$ mpicc gather.c
- [amao@amao991 mpi-study]$ mpiexec -f machinefile -n 5 ./a.out
- gatherBuf[0] = 0, gatherBuf[1] = 1, gatherBuf[2] = 2, gatherBuf[3] = 3, gatherBuf[4] = 4,
- total elapsed time = 0.009653
5. 总结
(1) 本例用了malloc在heap中开辟连续空间(数组)
int* gatherBuf = (int *)malloc(sizeof(int) * totalNumTasks); 而后用gatherBuf[i]的形式来逐个显示每个空间的值。
|