1.Int MPI_Group_rank(MPI_Group group,int *rank)
IN Group 进程组
OUT Rank 进程在进程组中的编号
如果进程不是进程组中的成员,则返回值RANK为MPI_UNDEFINED
2 .
Int MPI_Group_translate_ranks(MPI_Group group1 , int n ,int *ranks1 ,MPI_Group group2 ,int *ranks2)
IN Group1 进程组1
IN n ranks1和ranks2中数组元素的个数
IN ranks1 进程组1中有效编号组成的数组
IN group2 进程组2
OUT ranks2 ranks1中的元素在进程组2中的对应编号
如果属于进程组1的某个进程可以在ranks1中找到,而这个进程不属于进程组2,则在ranks2中对应ranks1的位置返回值为MPI_UNDEFINED
3 .Int MPI_Group_incl(MPI_Group group,int n,int *ranks,MPI_Group new group)
IN Group 进程组
IN n ranks数组中元素的个数和新进数组的大小
IN ranks 将在新进程组中出现的旧进程组中的编号
OUT newgroup 有ranks定义的顺序导出的新进程组
4 .Int MPI_Group_excl(MPI_Group group,int n,int *ranks,MPI_Group newgroup)
IN group 进程组
IN N ranks数组中元素的个数
IN ranks 在新进程组中不出现的旧进程组中的编号
OUT newgroup 旧进程组中不在ranks里的元素组成的新进程组
MPI通信子操作
1 . int MPI_Comm_Size(MPI_Comm comm,int *size)
IN comm 通信子
OUT size 通信子中的进程个数
2 . int MPI_Comm_rank(MPI_Comm comm,int *rank)
IN comm 通信子
OUT rank 通信子中的进程编号
3 . int MPI_Comm_dup(MPI_Comm comm,MPI_Comm *newcomm)
IN comm 通信子
OUT newcomm comm通信子的复制
4 . int MPI_Comm_Create(MPI_Comm comm,MPI_Group group,MPI_Comm *newcomm)
IN comm 通信子
IN group 通信子comm的一个子集
OUT newcomm 对应group的一个新通信子
5 . int MPI_Comm_Split(MPI_Comm comm,int color,int key,MPI_Comm *newComm)
IN comm 通信子
IN color 子集控制值
IN key 子集进程编号的顺序
OUT newcomm 由此产生的新通信子
划分comm所对应的进程组为不相交的子进程组,每个子进程组有一个共同的值color
6 . int MPI_Comm_free(MPI_Comm *Comm)
INOUT comm 通信子
示例:
下面通过一个例子来感受一下进程组和通信域在MPI多进程任务划分和处理上的应用。
代码做的事情如下:
(1)共有6个进程,在MPI_COMM_WORLD中的编号分别是{0,1,2,3,4,5}。
(2)将{1,3,5}进程形成一个新的通信域comm2;将编号为{0,2,4}的进程生成一个新的通信域comm1
(3)在comm1中执行MAX归约操作;在comm2中执行MIN归约操作;在MPI_COMM_WORLD中执行SUM归约操作
(4)显示各个通信域中归约操作的结果
#include "mpi.h"
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#define nodeNameLength 20
#define LEN 5
int main(int argc, char *argv[])
{
//MPI 组间通信
MPI_Init(&argc, &argv);
int world_rank, world_size;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Comm_rank(MPI_COMM_WORLD, &world_size);
MPI_Group world_group;
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
int n = 3;
const int ranks[3] = {0,2,4};
const int ori1[1] = {0};
const int ori2[1] = {1};
int root1, root2;
// 从world_group进程组中构造出来两个进程组
MPI_Group group1, group2;
MPI_Group_incl(world_group, n, ranks, &group1);
MPI_Group_excl(world_group, n, ranks, &group2);
// 根据group1 group2分别构造两个通信域
MPI_Comm comm1, comm2;
MPI_Comm_create(MPI_COMM_WORLD, group1, &comm1);
MPI_Comm_create(MPI_COMM_WORLD, group2, &comm2);
// 维护发送缓冲区和接受缓冲区
int i;
double *sbuf, *rbuf1, *rbuf2, *rbuf3;
sbuf = (double*)malloc(LEN*sizeof(double));
rbuf1 = (double*)malloc(LEN*sizeof(double));
rbuf2 = (double*)malloc(LEN*sizeof(double));
rbuf3 = (double*)malloc(LEN*sizeof(double));
srand(world_rank*100);
for(i=0; i<LEN; i++) sbuf[i] = i; // RAND_MAX;
fprintf(stderr,"rank %d:\t sendBuf is:", world_rank);
for(i=0; i<LEN; i++) fprintf(stderr,"%f\t",sbuf[i]);
fprintf(stderr,"\n");
//将一个组中的进程标识号转换成另一个组的进程标识号
MPI_Group_translate_ranks(world_group, 1, ori1, group1, &root1);
MPI_Group_translate_ranks(world_group, 1, ori2, group2, &root2);
// MPI_COMM_WORLD comm1 comm2分别执行不同的归约操作
if (MPI_COMM_NULL!=comm1) { // comm1
MPI_Reduce(sbuf, rbuf1, LEN, MPI_DOUBLE, MPI_MAX, root1, comm1);
int rank_1;
MPI_Comm_rank(comm1, &rank_1);
if (root1==rank_1) {
fprintf(stderr,"root1:%d,MAX:\t\n",root1);
for(i=0; i<LEN; i++) fprintf(stderr,"%f\t",rbuf1[i]);
fprintf(stderr,"\n");
}
}
else if (MPI_COMM_NULL!=comm2) { // comm2
MPI_Reduce(sbuf, rbuf2, LEN, MPI_DOUBLE, MPI_MIN, root2, comm2);
int rank_2;
MPI_Comm_rank(comm2, &rank_2);
if (root2==rank_2) {
fprintf(stderr,"root2:%d,MIN:\t\n",root2);
for(i=0; i<LEN; i++) fprintf(stderr,"%f\t",rbuf2[i]);
fprintf(stderr,"\n");
}
}
MPI_Reduce(sbuf, rbuf3, LEN, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); // MPI_COMM_WORLD
if (0==world_rank) {
fprintf(stderr,"SUM:\t\n");
for(i=0; i<LEN; i++) fprintf(stderr,"%f\t",rbuf3[i]);
fprintf(stderr,"\n");
}
// 清理进程组和通信域
if(MPI_GROUP_NULL!=group1) MPI_Group_free(&group1);
if(MPI_GROUP_NULL!=group2) MPI_Group_free(&group2);
if(MPI_COMM_NULL!=comm1) MPI_Comm_free(&comm1);
if(MPI_COMM_NULL!=comm2) MPI_Comm_free(&comm2);
MPI_Finalize();
}
结果:
rank 0: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
rank 1: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
root2:0,MIN:
0.000000 1.000000 2.000000 3.000000 4.000000
rank 2: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
rank 3: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
rank 4: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
rank 5: sendBuf is:0.000000 1.000000 2.000000 3.000000 4.000000
root1:0,MAX:
0.000000 1.000000 2.000000 3.000000 4.000000
SUM:
0.000000 6.000000 12.000000 18.000000 24.000000