MPI-3 非阻塞通信子複製和組集合通信子創建方法

本文從本人簡書博客同步過來

上一篇中我們介紹了 mpi4py 中的近鄰集合通信方法,下面我們將介紹 mpi4py 中的非阻塞通信子複製和組集合通信子創建方法。

非阻塞通信子複製方法 MPI.Comm.Idup 和組集合通信子創建方法 MPI.Comm.Create_group 都是 MPI-3 中新增的通信子創建方法。

在前面已經介紹了 MPI-1 和 MPI-2 中的通信子創建方法,其中 MPI.Comm.Dup 是一個阻塞的通信子複製方法,MPI.Comm.Create 是一個集合通信子創建方法,即處於調用該方法的通信子內的所有進程必須共同參與才能完成一個新的通信子的創建工作,即使所創建的新通信子只包含原通信子裏面的部分進程。MPI.Comm.Create 的集合操作性在某些情況下可能會遇到問題,比如說只要一個通信子內的某一個或幾個進程因出錯誤而死掉後,所有這個通信子上的集合操作都無法進行了,因爲集合操作要求通信子上的所有進程共同參與。我們可以考慮將該通信子中正常的進程創建成一個新的通信子,並進行後續的計算工作。一種自然的想法是調用該通信子的 MPI.Comm.Create 方法,但是因爲其集合操作性,我們無法在該通信子的某些進程死掉的情況下使用 MPI.Comm.Create 創建一個新的通信子,而且其它的集合通信子創建方法如 MPI.Comm.Dup,MPI.Comm.Split 等也都無法使用。MPI-1 和 MPI-2 中沒有提供非集合的通信子創建方法,此限制可能會導致直到程序退出該通信子上的所有集合操作都無法進行。

MPI-3 引進的 MPI.Comm.Idup 是 MPI.Comm.Dup 的非阻塞版本,可以通過將通信子創建和其它計算重疊而提高程序的運行效率。

MPI-3 引進的 MPI.Comm.Create_group 是一個非集合操作,改進了 MPI.Comm.Create 的缺陷,它可以在某個通信子上的部分進程參與的情況下下創建一個新的通信子。

方法接口

下面給出這兩個新的通信子創建方法的使用接口。

MPI.Comm.Idup(self)

非阻塞地複製當前通信子,返回一個由新創建的通信子 comm_new 和一個 MPI.Request 對象 req 組成的二元 tuple。注意:在沒有調用 req 的 Wait,Test 等方法以等待或測試該非阻塞調用完成之前,新通信子 comm_new 並未真正創建成功,不能進行通信工作。

MPI.Comm.Create_group(self, Group group, int tag=0)

在已有通信子 comm 環境下,利用 group 組創建新的通信子 newcomm,但不會複製原通信子中添加的屬性信息。是一個非集合操作方法,只要求處於 group 中的所有進程執行這個調用,對那些不在組 group 中的進程,返回的 newcomm 值爲 MPI.COMM_NULL。group 參數可以爲 MPI.GROUP_NULL。注意:如果 group 不是 comm 所關聯組的子集或者不同進程中變量 group 所包含的組內容不同,則會發生錯誤。tag 參數用來區分對該方法的多次調用。

例程

下面給出這兩個新方法的使用例程。

# Idup.py

"""
Demonstrates the usage of Idup and Create_group.

Run this with 4 processes like:
$ mpiexec -n 4 python Idup.py
"""

import numpy as np
from mpi4py import MPI


comm = MPI.COMM_WORLD
rank = comm.Get_rank()

# Idup
comm_dup, req = comm.Idup()
req.Wait()
recv_obj = comm_dup.scatter([1, 2, 3, 4], root=0)
print 'rank %d has %d' % (rank, recv_obj)

# make one process die
if rank == 0:
    # process 0 dies
    exit()
# other processes can still work

# Create_group
# sub_comm = comm.Create(comm.group.Excl([0])) # dead lock for Create
sub_comm1 = comm.Create_group(comm.group.Excl([0])) # OK for Create_group

print 'sub_comm1.rank %d   <->   comm.rank %d' % (sub_comm1.rank, rank)

sub_comm2 = comm.Create_group(comm.group.Excl([0, 1])) # OK for Create_group
if rank >=2:
    print 'sub_comm2.rank %d   <->   comm.rank %d' % (sub_comm2.rank, rank)
else:
    print sub_comm2 == MPI.COMM_NULL

sub_comm3 = comm.Create_group(MPI.GROUP_NULL) # OK for Create_group
print sub_comm3 == MPI.COMM_NULL

運行結果如下:

$ mpiexec -n 4 python Idup.py
rank 1 has 2
sub_comm1.rank 0   <->   comm.rank 1
True
True
rank 2 has 3
sub_comm1.rank 1   <->   comm.rank 2
sub_comm2.rank 0   <->   comm.rank 2
True
rank 3 has 4
sub_comm1.rank 2   <->   comm.rank 3
sub_comm2.rank 1   <->   comm.rank 3
True
rank 0 has 1

以上介紹了 MPI-3 中引進的非阻塞通信子複製和組集合通信子創建方法,在下一篇中我們將介紹 MPI-3 中增強的單邊通信方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章