本文从本人简书博客同步过来
在上一篇中我们介绍了 mpi4py 中的属性和命名操作,下面将介绍 mpi4py 中的错误处理。
MPI.Comm.Set_errhandler(self, Errhandler errhandler)
将错误处理函数 errhandler
与当前通信子对象关联。
MPI.Comm.Get_errhandler(self)
获取与当前通信子对象相关联的错误处理函数,为一个 MPI.Errhandler 类对象。
MPI.Comm.Call_errhandler(self, int errorcode)
激活通信子对象上的错误处理函数,处理的错误码为 errorcode
。MPI 标准中,通信子对象的默认错误处理函数为 MPI.ERRORS_ARE_FATAL,调用该方法时,如果没有指定其它错误处理函数,则默认地会调用 MPI.ERRORS_ARE_FATAL 停止该通信子组内的所有进程。不过需要注意的是,为了有助于 Python 的异常处理机制,mpi4py 中将 MPI.COMM_WORLD 和 MPI.COMM_SELF 的默认错误处理函数设置成了 MPI.ERRORS_RETURN。如果你需要将 mpi4py 中 MPI.COMM_WORLD 和 MPI.COMM_SELF 的错误处理函数传递给 C/C++/Fortran 库,推荐先将其错误处理函数恢复为默认的 MPI.ERRORS_ARE_FATAL,以防止调用库中发生的错误不会被注意到。
MPI.Win.Set_errhandler(self, Errhandler errhandler)
将错误处理函数 errhandler
与当前窗口对象关联。
MPI.Win.Get_errhandler(self)
获取与当前窗口对象相关联的错误处理函数,为一个 MPI.Errhandler 类对象。
MPI.Win.Call_errhandler(self, int errorcode)
激活窗口对象上的错误处理函数,处理的错误码为 errorcode
。MPI 标准中,窗口对象的默认错误处理函数为 MPI.ERRORS_ARE_FATAL,调用该方法时,如果没有指定其它错误处理函数,则默认地会调用 MPI.ERRORS_ARE_FATAL 停止构成该窗口对象组内的所有进程。不过需要注意的是,为了有助于 Python 的异常处理机制,mpi4py 中将新创建的窗口对象的默认错误处理函数设置成了 MPI.ERRORS_RETURN。如果你需要将 mpi4py 中窗口的错误处理函数传递给 C/C++/Fortran 库,推荐先将其错误处理函数恢复为默认的 MPI.ERRORS_ARE_FATAL,以防止调用库中发生的错误不会被注意到。
MPI.File.Get_errhandler(self)
将错误处理函数 errhandler
与当前文件句柄关联。
MPI.File.Set_errhandler(self, Errhandler errhandler)
获取与当前文件句柄相关联的错误处理函数,为一个 MPI.Errhandler 类对象。
MPI.File.Call_errhandler(self, int errorcode)
激活文件句柄上的错误处理函数,处理的错误码为 errorcode
。注意:不同于通信子和窗口对象上的默认错误处理函数,MPI 标准中文件句柄的默认错误处理函数为 MPI.ERRORS_RETURN,调用该方法时,如果没有指定其它错误处理函数,则默认地会调用 MPI.ERRORS_RETURN 直接返回,而不是停止进程。mpi4py 中将新创建的文件句柄的默认错误处理函数为 MPI.ERRORS_RETURN。
MPI 规定在上述 3 种对象错误处理函数内不能再直接或间接调用 3 种之一的错误处理函数,也就是说,3 种对象错误处理函数不可重入和递归,否则可能导致无限循环。
MPI.Errhandler.Free(self)
释放当前的 Errhandler 类对象。释放后的对象变为 MPI.ERRHANDLER_NULL。
MPI 为其内置的各种对象定义了错误处理函数,并提供了用户自定义和扩展机制,在 MPI 中错误信息及其处理由相应的错误类(error class),错误码(error code),错误处理函数(error handlers)等定义而成。基于 MPI 开发的第三方库可对原有的错误类扩展定义属于自己的错误处理机制。MPI 提供来一些函数来支持定义和定制错误处理框架,这主要包括:
MPI.Add_error_class()
添加并返回一个新的错误类。
MPI.Add_error_code(int errorclass)
将错误码与错误类 errorclass
相关联,并返回错误码。错误码由 MPI 环境根据预定的算法分配,以避免与已有的错误码冲突。
MPI.Add_error_string(int errorcode, string)
以错误码 errorcode
为中介,把一个错误信息字符串 string
与错误码和错误类关联起来。
MPI.Get_error_class(int errorcode)
返回与错误码 errorcode
相关联的错误类。
MPI.Get_error_string(int errorcode)
返回与错误码 errorcode
相关联的错误字符串。如果没有为该错误码定义相应的错误字符串,则返回空字符串。
在 mpi4py 中,当将错误处理函数设置成 MPI.ERRORS_RETURN 的时候,调用 MPI 函数或方法过程中出现的错误会以 MPI.Exception 类的异常对象的形式抛出,可以在程序中使用通常的 try … except … finally 异常处理机制进行异常捕获和处理。MPI.Exception 类是 RuntimeError 类的子类,其相关方法如下:
MPI.Exception.__init__(self, int ierr=0)
由错误类 ierr
构建一个 MPI.Exception 对象。
MPI.Exception.Get_error_class(self)
获取该异常对象的错误类,也可以通过对象属性 error_class 获取。
MPI.Exception.Get_error_code(self)
获取该异常对象的错误码,也可以通过对象属性 error_code 获取。
MPI.Exception.Get_error_string(self)
获取该异常对象的错误识别字符串,也可以通过对象属性 error_string 获取。
下面给出使用例程。
# errhandler.py
"""
Demonstrates error handling related operations.
Run this with 1 processes like:
$ mpiexec -n 1 python errhandler.py
or
$ python errhandler.py
"""
import numpy as np
from mpi4py import MPI
comm = MPI.COMM_WORLD
win = MPI.Win.Create(MPI.BOTTOM, 1, MPI.INFO_NULL, comm)
fh = MPI.File.Open(comm, 'temp', MPI.MODE_WRONLY | MPI.MODE_CREATE | MPI.MODE_DELETE_ON_CLOSE, MPI.INFO_NULL)
# error handler
for obj, name in [ (comm, 'MPI.Comm'), (win, 'MPI.Win'), (fh, 'MPI.File') ]:
eh = obj.Get_errhandler()
default_eh, eh_str = MPI.ERRORS_RETURN, 'MPI.ERRORS_RETURN'
print 'Default errhandler of %s == %s: %s' % (name, eh_str, eh == default_eh)
# set error handler to MPI.ERRORS_ARE_FATAL
obj.Set_errhandler(MPI.ERRORS_ARE_FATAL)
eh = obj.Get_errhandler()
assert eh == MPI.ERRORS_ARE_FATAL
# free the error handler
eh.Free()
# eh becomes MPI.ERRHANDLER_NULL after the Free operation
assert eh == MPI.ERRHANDLER_NULL
# recover the default errhandler
obj.Set_errhandler(default_eh)
# call error hander MPI.ERR_OTHER, which is known error not in list
obj.Call_errhandler(MPI.ERR_OTHER)
fh.Close()
# error class, error code, error string
# add a new error class
errclass = MPI.Add_error_class()
# add an error code to the new error class
errcode = MPI.Add_error_code(errclass)
# associate an error string with an the error errorcode
MPI.Add_error_string(errcode, 'Example error string')
print 'The new error class:', MPI.Get_error_class(errcode)
print 'The new error string:', MPI.Get_error_string(errcode)
# MPI.Exception
# errexc = MPI.Exception(errclass)
# create an MPI.Exception object from MPI.ERR_OTHER
errexc = MPI.Exception(MPI.ERR_OTHER)
print 'MPI.Exception is a subclass of RuntimeError:', isinstance(errexc, RuntimeError)
print 'Error class of MPI.ERR_OTHER:', errexc.Get_error_class()
print 'Error code of MPI.ERR_OTHER:', errexc.Get_error_code()
print 'Error string of MPI.ERR_OTHER:', errexc.Get_error_string()
# show exception catch
try:
# try to free MPI.COMM_WORLD
MPI.COMM_WORLD.Free()
except MPI.Exception as e:
print 'Error class of the Free op:', e.Get_error_class()
print 'Error code of the Free op:', e.Get_error_code()
print 'Error string of the Free op:', e.Get_error_string()
运行结果如下:
$ python errhandler.py
Default errhandler of MPI.Comm == MPI.ERRORS_RETURN: True
Default errhandler of MPI.Win == MPI.ERRORS_RETURN: True
Default errhandler of MPI.File == MPI.ERRORS_RETURN: True
The new error class: 72
The new error string: Example error string
MPI.Exception is a subclass of RuntimeError: True
Error class of MPI.ERR_OTHER: 16
Error code of MPI.ERR_OTHER: 16
Error string of MPI.ERR_OTHER: MPI_ERR_OTHER: known error not in list
Error class of the Free op: 5
Error code of the Free op: 5
Error string of the Free op: MPI_ERR_COMM: invalid communicator
以上介绍了 mpi4py 中的错误处理,在下一篇中我们将介绍 mpi4py 中的 info 和 assertion。