在上一篇中我们介绍了 mpi4py 中的错误处理,下面我们将介绍 mpi4py 中的 info 和 assertion。
MPI 允许用户提供两种类型的与应用有关的信息:hints 和 assertions。hints 是应用中所做的有助于提高程序性能的选项,MPI 实现可以忽略用户提供的 hints 而不影响程序的正确性;assertions 是用户(编程者)给 MPI 实现的有关其应用程序行为的保证——如果程序给出的某个 assertion 并不正确,MPI 实现可能会产生错误的结果。在 MPI 中大多数的 hints 都是通过 MPI.Info 对象传递给 MPI 实现的,而 assertions 则是传递给一些 MPI 函数/方法的整数值。用户可以不提供 hints 或 assertions,应用程序可以在不提供它们的情况下正确运行,但是,提供合适的 hints 或正确的 assertions 可以提高应用程序的性能。hints 和 assetions 都是可移植的。除了 MPI 标准提供的 hints 外,不同的 MPI 实现可能会定义额外的不同的 hints,用户应该查看相关的文档以了解可用的 hints 及其作用。
MPI-2 引进了 Info 对象,MPI 中的很多函数都使用了 info 参数,Info 参数以 <key,value> 字符串二元组的形式定义信息。MPI 本身也使用一些预留的关键字来保存环境与外部交互,以及其他一些属性信息。关键字和值分别由 MPI.MAX_INFO_KEY 和 MPI.MAX_INFO_VAL 定义上限。
hints 和 Info 对象
一般接口
MPI.Info.Create(type cls)
创建一个 Info 对象,将其 <key,value> 二元组初始化为空。
MPI.Info.Dup(self)
复制当前 Info 对象,包括其中的 <key,value> 二元组。
MPI.Info.Delete(self, key)
从当前 Info 对象中删除 <key,value> 二元组,如果 key
参数指定的关键字不存在,则会抛出 MPI.Exception 异常。
MPI.Info.Free(self)
删除并释放当前 Info 对象,将其值设置为 MPI.INFO_NULL。
MPI.Info.Set(self, key, value)
为当前 Info 对象设置二元组 <key,value>,如果 key
所指定的关键字已经存在,则覆盖其原有的值。如果 key
或 value
参数的字符串长度超过上限,则会抛出 MPI.Exception 异常。
MPI.Info.Get(self, key, int maxlen=-1)
从当前 Info 对象中获取关键字 key
的值,如果该关键字不存在,则返回 None。maxlen
是获取的值的最大长度,如果该长度小于值的实际长度,则返回的是被截断的值,maxlen
如果为小于 0 或大于 MPI.MAX_INFO_VAL,则会使用 MPI.MAX_INFO_VAL。
MPI.Info.Get_nkeys(self)
返回当前 Info 对象中定义的关键字总数。
MPI.Info.Get_nthkey(self, int n)
返回当前 Info 对象中第 n
个关键字,关键字编号从 0 开始。
类似与字典的接口
MPI.Info.__len__(self)
使用 len 函数获取当前 Info 对象中定义的关键字总数。
MPI.Info.__contains__(self, object key)
使用 in 来测试当前 Info 对象中是否包含 key
关键字。
MPI.Info.__iter__(self)
迭代器接口。
MPI.Info.__getitem__(self, object key)
使用 info[key] 获取 key
对应的值。
MPI.Info.__setitem__(self, object key, object value)
使用 info[key] = value 的方式为当前 Info 对象设置 <key,value> 二元组。
MPI.Info.__delitem__(self, object key)
使用 del info[key] 的方式从当前 Info 对象中删除 <key,value> 二元组。
MPI.Info.get(self, object key, object default=None)
获取当前 Info 对象的 key
关键字对应的值,如果 key
不存在,则返回 default
。
MPI.Info.keys(self)
返回当前 Info 对象的所有关键字,结果是一个 list。
MPI.Info.values(self)
返回当前 Info 对象的所有值,结果是一个 list。
MPI.Info.items(self)
返回当前 Info 对象的所有 <key,value> 二元组,结果是一个 list,其每一个元素为一个二元 tuple。
MPI.Info.update(self, other=(), **kwds)
以 other
和 kwds
中的 key 和 value 来更新当前 Info 对象的关键字和值,类似于 Python 字典的 update 操作。
MPI.Info.copy(self)
复制当前 Info 对象,包括其中的 <key,value> 二元组。同 MPI.Info.Dup。
MPI.Info.clear(self)
删除当前 Info 对象中的所有 <key,value> 二元组。
MPI-3 新方法
因为 Info 对象可以潜在地帮助 MPI 实现提供更高的性能,MPI-3 中新增了若干与 Info 相关的方法,允许设置和获取通信子,窗口以及文件句柄的 Info。另外,MPI-3 中增加一个新的通信子复制方法 MPI.Comm.Dup_with_info,该方法与 MPI.Comm.Dup 的作用类似,不过允许在复制通信子对象的时候为其设置一个新的 Info 对象,而不是将原通信子的 Info 对象也一并复制过来。该方法对 MPI 库的开发非常有用,因为通信子复制方法通常被库的开发者用来在库内部创建一个私有的通信子,以防止库内的通信操作对外部的通信产生干扰,库在复制通信子的过程中可能并不需要将用户设置在原通信子上的某些 info 键值对也一并复制过去,因此可以使用 MPI.Comm.Dup_with_info 在复制的过程中为其设置一个新的库所需要的 Info 对象。下面是这些新方法的使用接口。注意:在 mpi4py 中,MPI.Comm.Dup 方法在传递一个有效的 info
参数时等价于 MPI.Comm.Dup_with_info。
通信子
MPI.Comm.Dup(self, Info info=None)
MPI.Comm.Dup_with_info(self, Info info)
MPI.Comm.Set_info(self, Info info)
MPI.Comm.Get_info(self)
窗口
MPI.Win.Set_info(self, Info info)
MPI.Win.Get_info(self)
文件
MPI.File.Set_info(self, Info info)
MPI.File.Get_info(self)
assertions
MPI 中,assertions 主要使用在单边通信的相关操作中,比如下面的一些方法接口:
MPI.Win.Fence(self, int assertion=0)
MPI.Win.Lock(self, int rank, int lock_type=LOCK_EXCLUSIVE, int assertion=0)
MPI.Win.Lock_all(self, int assertion=0)
MPI.Win.Post(self, Group group, int assertion=0)
MPI.Win.Start(self, Group group, int assertion=0)
这些方法及其 assertion 参数的作用和可能取值在单边通信和MPI-3 中增强的单边通信中作过相应的介绍。
例程
下面给出使用例程。
# info.py
"""
Demonstrates the usage of info and assertion.
Run this with 1 processes like:
$ mpiexec -n 1 python info.py
or
$ python info.py
"""
import numpy as np
from mpi4py import MPI
comm = MPI.COMM_WORLD
# create an info object
info = MPI.Info.Create()
# dupicate the info
info1 = info.Dup()
# free the duplicated info
info1.Free()
# becomes MPI.INFO_NULL after the free op
assert info1 == MPI.INFO_NULL
try:
# try to delete a non-existed key from info
info.Delete('a')
except MPI.Exception as e:
print e.error_string
# set key and value
info.Set('k1', 'v1')
info.Set('k2', 'v2')
info.Set('k3', 'v3')
print 'k1:', info.Get('k1')
print 'nkeys:', info.Get_nkeys()
print 'the second key:', info.Get_nthkey(1)
try:
# try to set a key with length > MPI.MAX_INFO_KEY
info.Set('k' * (MPI.MAX_INFO_KEY + 1), 'v')
except MPI.Exception as e:
print e.error_string
try:
# try to set a value with length > MPI.MAX_INFO_VAL
info.Set('k', 'v' * (MPI.MAX_INFO_VAL + 1))
except MPI.Exception as e:
print e.error_string
# dict interface
print 'len(info):', len(info)
print 'k1 in info:', 'k1' in info
# __iter__ method
for k in info:
print k
info['k4'] = 'v4'
print 'k4:', info['k4']
del info['k4']
print 'k4:', info.get('k4', 'v4_new')
print 'keys:', info.keys()
print 'values:', info.values()
print 'items:', info.items()
info.update({'k1': 'v1_new', 'k5': 'k5_new'})
print 'items after update:', info.items()
info.clear()
print 'items after clea:', info.items()
# info with comm
comm_info = MPI.Info.Create()
comm.Set_info(comm_info)
comm.Get_info()
info_dup = MPI.Info.Create()
comm.Dup_with_info(info_dup)
运行结果如下:
$ python info.py
MPI_ERR_INFO_NOKEY: unknown key for given info object
k1: v1
nkeys: 3
the second key: k2
MPI_ERR_INFO_KEY: invalid key argument for info object
MPI_ERR_INFO_VALUE: invalid value argument for info object
len(info): 3
k1 in info: True
k1
k2
k3
k4: v4
k4: v4_new
keys: ['k1', 'k2', 'k3']
values: ['v1', 'v2', 'v3']
items: [('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')]
items after update: [('k1', 'v1_new'), ('k2', 'v2'), ('k3', 'v3'), ('k5', 'k5_new')]
items after clea: []
以上介绍了 mpi4py 中的 info 和 assertion,在下一篇中我们将介绍 mpi4py 中的 Status 对象。