Boost C++ 库

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

Python 绑定

快速入门
传输用户定义的数据
集合通信
骨架/内容机制
C++/Python MPI 兼容性
参考

Boost.MPI 通过 boost.mpi 模块,从 Python 编程语言提供了一种替代的 MPI 接口。 Boost.MPI Python 绑定构建于 C++ Boost.MPI 之上,使用 Boost.Python 库,在一个动态的、面向对象的语言中提供了 Boost.MPI 的几乎所有功能。

Boost.MPI Python 模块可以从 libs/mpi/build 目录构建和安装。只需按照 C++ Boost.MPI 的配置安装说明进行操作。一旦你安装了 Python 模块,请确保安装位置在你的 PYTHONPATH 中。

开始使用 Boost.MPI Python 模块就像导入 boost.mpi 一样容易。我们的第一个 “Hello, World!” 程序只有两行代码

import boost.mpi as mpi
print "I am process %d of %d." % (mpi.rank, mpi.size)

继续运行这个程序,使用多个进程。务必从 mpirun 调用 python 解释器,例如,

mpirun -np 5 python hello_world.py

这将返回如下输出

I am process 1 of 5.
I am process 3 of 5.
I am process 2 of 5.
I am process 4 of 5.
I am process 0 of 5.

Boost.MPI 中的点对点操作在 Python 中与在 C++ 中具有几乎相同的语法。我们可以编写一个简单的双进程 Python 程序,通过传输 Python 字符串来打印 “Hello, world!”

import boost.mpi as mpi

if mpi.world.rank == 0:
  mpi.world.send(1, 0, 'Hello')
  msg = mpi.world.recv(1, 1)
  print msg,'!'
else:
  msg = mpi.world.recv(0, 0)
  print (msg + ', '),
  mpi.world.send(0, 1, 'world')

此 Python 代码与C++ 教程中的示例之间只有一些显著的区别。首先,我们不需要在 Python 中编写任何初始化代码:仅加载 boost.mpi 模块即可进行适当的 MPI_InitMPI_Finalize 调用。其次,我们正在通过 MPI 在进程之间传递 Python 对象。任何可以被 pickle 的 Python 对象都可以被传输;下一节将更详细地描述 Boost.MPI Python 层如何传输对象。最后,当我们使用 recv 接收对象时,我们不需要指定类型,因为 Python 对象的传输是多态的。

当在 Python 中实验 Boost.MPI 时,不要忘记始终可以通过 pydoc 获得帮助:只需在命令行中传递模块或模块实体的名称(例如,pydoc boost.mpi.communicator),即可接收完整的参考文档。当有疑问时,尝试一下!

Boost.MPI 可以通过几种不同的方式传输用户定义的数据。最重要的是,它可以通过在发送方 pickle 任意 Python 对象并在接收方 unpickle 它们,从而传输这些对象,允许任意复杂的 Python 数据结构与 MPI 互操作。

Boost.MPI 还支持通过其 C++ 接口,对(已暴露给 Python 的)C++ 对象进行高效的序列化和传输。任何提供(反)序列化例程的 C++ 类型,只要这些例程满足 Boost.Serialization 库的要求,都有资格进行此优化,但该类型必须预先注册。要注册 C++ 类型,请调用 C++ 函数 register_serialized。如果你的 C++ 类型来自其他 Python 模块(很可能是这种情况!),则这些模块需要链接到 boost_mpiboost_mpi_python 库,如安装部分所述。请注意,你需要链接到 Boost.MPI Python 扩展模块。

最后,Boost.MPI 支持将对象的结构与其存储的数据分离,允许将这两部分分开传输。这种 “骨架/内容” 机制在后面的章节中会更详细地描述,它是一种通信优化,适用于内部数据频繁更改的具有固定数据结构的问题。

Boost.MPI 支持所有的 MPI 集合通信(scatterreducescanbroadcast 等),适用于任何可以通过点对点通信操作传输的数据类型。对于需要用户指定操作的 MPI 集合通信(例如,reducescan),该操作可以是任意 Python 函数。例如,可以使用 all_reduce 连接字符串

mpi.all_reduce(my_string, lambda x,y: x + y)

以下模块级函数实现了 MPI 集合通信: all_gather 收集来自所有进程的值。 all_reduce 组合来自所有进程的结果。 all_to_all 每个进程向所有其他进程发送数据。 broadcast 从一个进程向所有其他进程广播数据。 gather 将来自所有进程的值收集到根进程。 reduce 将来自所有进程的结果组合到根进程。 scan 所有进程的值的前缀归约。 scatter 将存储在根进程的值分散到所有进程。

Boost.MPI 提供了一种骨架/内容机制,该机制允许将大型数据结构的传输分成两个独立的阶段,其中数据结构的骨架(或“形状”)首先发送,而数据结构的内容(或“数据”)稍后发送,可能会发送多次,只要自骨架传输以来结构没有改变。当数据结构很大且其形状固定时,骨架/内容机制可以提高性能,因为虽然骨架需要序列化(它的大小未知),但内容传输是固定大小的,并且可以在没有额外副本的情况下完成。

要从 Python 中使用骨架/内容机制,你必须首先从 C++向骨架/内容机制注册你的数据结构类型。注册函数是 register_skeleton_and_content,并且位于 <boost/mpi/python.hpp> 头文件中。

一旦你注册了你的 C++ 数据结构,你就可以使用 skeleton() 提取该数据结构实例的骨架。结果 skeleton_proxy 可以通过正常的发送例程传输,例如,

mpi.world.send(1, 0, skeleton(my_data_structure))

skeleton_proxy 对象可以在另一端通过 recv() 接收,它会在其 "object" 属性中存储一个新创建的数据结构实例,该实例具有与发送者相同的“形状”

shape = mpi.world.recv(0, 0)
my_data_structure = shape.object

一旦骨架被传输,内容(通过 get_content 访问)可以以非常相似的方式传输。但是请注意,接收方也在其接收调用中指定 get_content(my_data_structure)

if mpi.rank == 0:
  mpi.world.send(1, 0, get_content(my_data_structure))
else:
  mpi.world.recv(0, 0, get_content(my_data_structure))

当然,如果数据结构中的值(但不是其形状)发生变化,内容的这种传输可以重复发生。

骨架/内容机制是一种结构化的方式,可以利用自定义 MPI 数据类型和 MPI_BOTTOM 之间的交互,以消除额外的缓冲区复制。

Boost.MPI 是一个 C++ 库,其功能已通过 Boost.Python 库暴露给 Python。由于 Boost.MPI Python 绑定直接构建在 C++ 库之上,并且 C++ 库的几乎所有功能都可以在 Python 中使用,因此使用 Boost.MPI 的混合 C++/Python 程序可以交互,例如,从 Python 发送一个值,但在 C++ 中接收该值(或反之亦然)。然而,这样做需要一些注意。因为 Python 对象是动态类型的,所以 Boost.MPI 会随对象序列化形式一起传输类型信息,以便即使在不知道其类型的情况下也可以接收对象。这种机制与 C++ 对应机制不同,在 C++ 对应机制中,传输值的静态类型始终是已知的。

在 Boost.MPI 的 C++ 和 Python 视图之间进行通信的唯一方法是完全使用 Python 对象。对于 Python 来说,这是正常状态,因此不会有任何改变。对于 C++ 来说,这意味着发送和接收来自 Boost.Python 库的 boost::python::object 类型的值。例如,假设我们想从 Python 传输一个整数值

comm.send(1, 0, 17)

在 C++ 中,我们会将该值接收到一个 Python 对象中,然后 extract 一个整数值

boost::python::object value;
comm.recv(0, 0, value);
int int_value = boost::python::extract<int>(value);

在未来,Boost.MPI 将被扩展以允许与 C++ Boost.MPI 和 C MPI 绑定改进的互操作性。

Boost.MPI Python 模块 boost.mpi 有其自己的参考文档,也可以使用 pydoc(从命令行)或 help(boost.mpi)(从 Python 解释器)获得。


PrevUpHomeNext