MPI Group通信

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   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝鲸123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值