博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【MPI学习7】MPI并行程序设计模式:MPI的进程组和通信域
阅读量:7069 次
发布时间:2019-06-28

本文共 4726 字,大约阅读时间需要 15 分钟。

基于都志辉老师MPI编程书中的第15章内容。

通信域是MPI的重要概念:MPI的通信在通信域的控制和维护下进行 → 所有MPI通信任务都直接或间接用到通信域这一参数 → 对通信域的重组和划分可以方便实现任务的划分

 

(1)通信域(communicator)是一个综合的通信概念。其包括上下文(context),进程组(group),虚拟处理器拓扑(topology)。其中进程组是比较重要的概念,表示通信域中所有进程的集合。一个通信域对应一个进程组。

 

(2)进程(process)与进程组(group)的关系。每个进程是客观上唯一的(一个进程对应一个pid号);同一个进程可以属于多个进程组(每个进程在不同进程组中有个各自的rank号);同一个进程可以属于不同的进程组,因此也可以属于不同的通信域。

 

(3)通信域产生的方法。根据看过的资料,大概有三种方法,先简要了解路子即可:

  a. 在已有通信域基础上划分获得:MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm)  

   b. 在已有通信域基础上复制获得:MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)

     c. 在已有进程组的基础上创建获得:MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm)

 

(4)进程组产生的方法。进程组(group)可以当成一个集合的概念,可以通过“子、交、并、补”各种方法。所有进程组产生的方法都可以套到集合的各种运算,用到的时候现看函数就可以了。

 

(5)“当前进程”与“通信域产生函数”。如果在已有进程组的基础上创建新的通信域(即(3)中c方法),则newcomm有两种结果:如果调用MPI_Comm_create的当前进程在group中,则newcomm就是新产生的通信域对象;如果调用MPI_Comm_create的当前进程不在group中,则newcomm就是MPI_COMM_NULL。由于MPI是多进程编程,类似“当前进程”与“通信域产生函数”这种情况会比较频繁的出现,在设计思路上要适应并行编程这种改变。

 

(6)不同通信域间互不干扰。“互不干扰”严格来说并不完全正确,这里想说的意思是:同一个进程,可以属于不同的通信域;同一个进程可以同时参与不同通信域的通信,互不干扰。

 

 

下面通过一个例子来感受一下进程组和通信域在MPI多进程任务划分和处理上的应用。

代码做的事情如下:

(1)共有6个进程,在MPI_COMM_WORLD中的编号分别是{0,1,2,3,4,5}。

(2)将{1,3,5}进程形成一个新的通信域comm1;将编号为{0,2,4}的进程生成一个新的通信域comm2

(3)在comm1中执行MAX归约操作;在comm2中执行MIN归约操作;在MPI_COMM_WORLD中执行SUM归约操作

(4)显示各个通信域中归约操作的结果

具体代码如下:

 

1 #include "mpi.h" 2 #include 
3 #include
4 5 #define LEN 5 6 7 int main(int argc, char *argv[]) 8 { 9 MPI_Init(&argc, &argv);10 int world_rank, world_size;11 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);12 MPI_Comm_rank(MPI_COMM_WORLD, &world_size);13 14 MPI_Group world_group;15 MPI_Comm_group(MPI_COMM_WORLD, &world_group);16 17 int n = 3;18 const int ranks[3] = {
1,3,5};19 const int ori1[1] = {
1};20 const int ori2[1] = {
0};21 int root1, root2;22 23 // 从world_group进程组中构造出来两个进程组24 MPI_Group group1, group2;25 MPI_Group_incl(world_group, n, ranks, &group1);26 MPI_Group_excl(world_group, n, ranks, &group2);27 // 根据group1 group2分别构造两个通信域28 MPI_Comm comm1, comm2;29 MPI_Comm_create(MPI_COMM_WORLD, group1, &comm1);30 MPI_Comm_create(MPI_COMM_WORLD, group2, &comm2);31 32 // 维护发送缓冲区和接受缓冲区33 int i;34 double *sbuf, *rbuf1, *rbuf2, *rbuf3;35 sbuf = malloc(LEN*sizeof(double));36 rbuf1 = malloc(LEN*sizeof(double));37 rbuf2 = malloc(LEN*sizeof(double));38 rbuf3 = malloc(LEN*sizeof(double));39 srand(world_rank*100);40 for(i=0; i

 

 

代码执行结果如下:

 

可以看到:

a. MIN归约操作针对的是{0,2,4}

b. MAX归约操作针对的是{1,3,5}

c. SUM归约操作针对的是{0,1,2,3,4,5}

d. SUM与MIN或MAX归约操作在时间上可能是重叠的,参与归约操作的进程也有重叠,但在结果上没有互相干扰。

 

(7)组间通信域不同的通信域之间也可以通信,核心的操作是需要构造一个新的通信域类型——组间通信域。与一般的通信域不同,组间通信域包含两个进程组:本地进程组,远程进程组。通过组间通信域可以实现上述两个不同进程组内进程之间的通信。组间通信域的创建,需要在本地组和远程组中的相关进程中都调用创建语句,而且创建语句的参数中local_leader和remote_leader还是对称的。

 

1 #include "mpi.h" 2 #include 
3 #include
4 5 int main(int argc, char *argv[]) 6 { 7 MPI_Comm myComm; // 标示本地子组的组内通信域 8 MPI_Comm myFirstComm; // 组间通信域 9 MPI_Comm mySecondComm; // 组间通信域10 int color; // split用到的key11 int rank;12 13 MPI_Init(&argc, &argv);14 MPI_Comm_rank(MPI_COMM_WORLD, &rank);15 16 // 划分子通信域17 // split是如何划分的 翻阅了英文的mpi tutorial教程18 // 通过split函数中第三个参数来控制 当前进程在新的通信域中的新rank值大小19 color = rank % 3;20 MPI_Comm_split(MPI_COMM_WORLD, color, rank, &myComm);21 22 // 建立组间通信域23 // 需要确定的问题是: 24 // 1. A1和A2构造的是01之间的通信域 A1的local leader和remote leader与A2的local leader和remote leader是不是互相对应的25 // 2. 同理 B1和B2构造的是12之间的组间通信域 local leader和remote leader是否也是互相对应的 26 // 这是可以保证的 通过MPI_Comm_split语句中的第三个参数来保证27 if (0==color) {28 // 01之间的组间通信域29 // 1. 本地组的leader是0 30 // 2. remote组的leader在MPI_COMM_WORLD中的rank是131 // 3. tag是1 (tag起到什么作用?)32 // 4. 组间通信域存在myFirstComm中33 MPI_Intercomm_create(myComm, 0, MPI_COMM_WORLD, 1, 1, &myFirstComm); // A134 }35 else if (1==color) {36 // 01之间的组间通信域37 // 1. 本地组的leader是0 (本地组leader0应该是MPI_COMM_WORLD中的1 这是如何保证的?)38 // 2. 同理, MPI_COMM_WORLD中的0应该是color=0那个组中rank为0的进程 这是如何保证的?39 MPI_Intercomm_create(myComm, 0, MPI_COMM_WORLD, 0, 1, &myFirstComm); // A240 // 12之间的组间通信域41 MPI_Intercomm_create(myComm, 0, MPI_COMM_WORLD, 2, 12, &mySecondComm); // B142 }43 else if (2==color) {44 // 21之间的组间通信域45 MPI_Intercomm_create(myComm, 0, MPI_COMM_WORLD, 1, 12, &myFirstComm); // B246 }47 48 if (0==color || 2==color) {49 MPI_Comm_free(&myFirstComm);50 }51 else if (1==color) {52 MPI_Comm_free(&myFirstComm);53 MPI_Comm_free(&mySecondComm);54 }55 MPI_Finalize();56 }

 

转载于:https://www.cnblogs.com/xbf9xbf/p/5239094.html

你可能感兴趣的文章
CentOS 7.0安装配置LAMP服务器(Apache+PHP+MariaDB)
查看>>
Django 跨表查询--神奇的双下划线和点
查看>>
h3cte D图 搭建
查看>>
Linux 文件基本属性
查看>>
【转】js获取当前指定的前几天的日期(如当前时间的前七天的日期)
查看>>
javascript中对象字面量的理解
查看>>
centos 普通用户获得sudo超级权限
查看>>
Web内容管理系统 Magnolia
查看>>
tmux命令使用总结
查看>>
百度--买帽子
查看>>
SDWebImage的使用
查看>>
PC端和移动端测试区别
查看>>
TCP/IP中的四元组、五元组、七元组
查看>>
用代码告诉你“问世间情为何物,直教人生死相许”
查看>>
(PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
查看>>
使用sqlite保存数据返回主键
查看>>
js循环生成多个easyui datagrid数据网格时,初始化表格
查看>>
Python编程笔记(第三篇)【补充】三元运算、文件处理、检测文件编码、递归、斐波那契数列、名称空间、作用域、生成器...
查看>>
获取用户信息
查看>>
洛谷P3952 时间复杂度
查看>>