mpi学习日志(7):mpi4py与通信子,通信组

来源:互联网 发布:手机黑客攻击软件 编辑:程序博客网 时间:2024/05/20 21:47

从第一篇笔记开始,我们就使用了comm这个对象.

而且,几乎每次新学习的函数,都是这个comm的一个方法.

今天,我们就来重新认识comm,它到底是什么?


1.通信子

comm是一个通信子.什么是通信子?

通信子其实就是一个对讲机,每个进程都有一个对讲机.

通过对讲机,你可以和某个人对话,也可以对全部人发出广播.


2.通信组

警察有警察之间的对讲机,盗贼有盗贼之间的对讲机.

显然,警察的对讲机是不应该能和盗贼的对讲机通信的(不包括偷听).

这样的话,我们就有了通信组的概念.

警察之间形成一个通信组,盗贼之间形成一个通信组.


3.MPI里的通信组

MPI里有一个类Group,它就是充当了通信组的角色.

当我们有一个对讲机comm的时候,我们通过Get_group()的方法可以得到对应的Group对象.

Group对象有什么用?它可以用来创建新的通信组!


4.MPI里的默认通信子

我们一开始就用到了一个系统帮我们创建的全局通信子,就是COMM_WORLD,它包含了所有的进程.

其实还有两个系统默认创建的通信子,一个是COMM_SELF,另一个是COMM_NULL.

COMM_SELF仅仅包含了当前进程,而COMM_NULL则什么进程都没有包含.

在下面的代码中,我们将使用到COMM_NULL.


5.创建新通信组

在实际开发中,我们往往不止需要一个全局的通信组,还需要很多小型的通信组,我们需要创建新通信组.

其实准确来说是创建新通信子,因为通信组只是一份名单,而通信需要的是对讲机!

某个系列的对讲机一定有对应的某份名单,而某份名单不一定有对应的对讲机.

要创建新通信子,我们的过程是这样的:

(1)获取一个旧的通信组(通常是利用COMM_WORLD获取)

(2)对这个通信组进行添加和删减,以达到我们的目标

(3)通过旧通信子的Create方法创建新通信子

下面我们会在6个进程中,让后3个进程单独创建一个新的通信组.


代码:



运行结果:



代码解释:

第8行获取了全局通信子的通信组,第9行调用了Excl方法,得到了一个剔除了前3个进程的新通信组(具体的含义会在下一篇笔记说到).

然后我们用Create()方法,把group作为参数送进去,就会得到一个新的通信子new_comm.


注意到,对于第3,4,5个进程来说,它们会得到新通信子.但是,对第0,1,2个进程来说,它们不应该得到新通信子.

那样的话,是否需要全部进程都执行Create()这个方法?

答案是一定要的.实际上这个方法有一个barrier的过程,也就是全局同步.

在comm这个通信子里的所有进程,必须都调用Create()这个方法,MPI才会生成并返回新的通信子.

不相信的话,你可以让某个进程不调用Create(),结果是其他进程会被阻塞住.


那么新问题又到了,对第0,1,2个进程来说,它们得到的new_comm是个什么玩意?

没错,从代码第13行你已经发现了,它会是一个空通信子COMM_NULL.

总的来说就是,旧通信子的所有进程都调用Create()方法.对于在新通信组的进程会得到新通信子,而不在新通信组的进程会得到空通信子.

空通信子就是这样使用的,并且如果你像普通通信子一样调用它的方法,会抛出异常.


从输出结果可以看到新通信子对它的进程重新分配了rank.

也就是说,对某个进程,它在不同的通信组会有不同的rank,这也是把它称为rank而不是id的原因.

因此,在不同通信组进行通信的时候,这个进程使用的rank是不同的.这有点像,在不同的场合,人有不同的身份.


通信组示意图:



0 0
原创粉丝点击