python中mpi4py的所有基础使用案例详解

橘子海
橘子海
发布时间:2026-10-16 | 5人浏览过
原创

本文详细解析Python中mpi4py库的基础用法,涵盖阻塞与非阻塞点对点通信、广播(Bcast)、分散(Scatter)、聚集(Gather)及全收集(Allgather)等核心集体通信机制。通过10个具体代码案例,演示如何利用MPI实现多进程数据分发与同步,特别针对NumPy数组的大规模并行处理提供了实用示例,帮助开发者快速掌握分布式计算的核心概念。

python中mpi4py的基础使用

在大多数情况下,MPI程序可以通过mpiexec命令来执行。具体到Python环境,运行脚本的标准方式如下所示:

$ mpiexec -n 4 python script.py

案例1:测试comm.send 和comm.recv函数,代码如下

from mpi4py import MPI

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

if rank == 0:
    data = {'a': 7, 'b': 3.14}
    comm.send(data, dest=1, tag=11)
elif rank == 1:
    data = comm.recv(source=0, tag=11)

其中,rank表示当前进程的编号,其总数对应于mpiexec -n参数中指定的n值,且最大进程数受限于计算机CPU的核心数量。dest参数指定接收数据的目标进程ID,tag作为消息标签在此处可忽略,source则标识数据来源的进程rank。

案例2:具有非阻塞通讯的python对象

from mpi4py import MPI

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

if rank == 0:
    data = {'a': 7, 'b': 3.14}
    req = comm.isend(data, dest=1, tag=11)
    req.wait()
elif rank == 1:
    req = comm.irecv(source=0, tag=11)
    data = req.wait()

案例3: 快速发送实例

注意此处Send和Recv首字母大写,这是mpi4py中专门用于高效传输NumPy数组数据的方法。

from mpi4py import MPI
import numpy

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

# passing MPI datatypes explicitly
if rank == 0:
    data = numpy.arange(1000, dtype='i')
    comm.Send([data, MPI.INT], dest=1, tag=77)
elif rank == 1:
    data = numpy.empty(1000, dtype='i')
    comm.Recv([data, MPI.INT], source=0, tag=77)

# automatic MPI datatype discovery
if rank == 0:
    data = numpy.arange(100, dtype=numpy.float64)
    comm.Send(data, dest=1, tag=13)
elif rank == 1:
    data = numpy.empty(100, dtype=numpy.float64)
    comm.Recv(data, source=0, tag=13)

案例4:集体通讯,广播机制

广播机制的作用是将root=0进程中的所有数据复制并发送到集群中的每一个其他进程。

from mpi4py import MPI

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

if rank == 0:
    data = {'key1' : [7, 2.72, 2+3j],
            'key2' : ( 'abc', 'xyz')}
else:
    data = None
data = comm.bcast(data, root=0)

案例5:scatter,将root=0下的数据一次分发到各个rank下

from mpi4py import MPI

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

if rank == 0:
    data = [(i+1)**2 for i in range(size)]
else:
    data = None
data = comm.scatter(data, root=0)
assert data == (rank+1)**2

案例6:gather,将所有rank下的数据收集到root下

from mpi4py import MPI

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

data = (rank+1)**2
data = comm.gather(data, root=0)
if rank == 0:
    for i in range(size):
        assert data[i] == (i+1)**2
else:
    assert data is None

案例7,numpy的广播机制

与之前的send/recv类似,这里使用大写的Bcast方法来处理NumPy数组的广播操作。

from mpi4py import MPI
import numpy as np

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

if rank == 0:
    data = np.arange(100, dtype='i')
else:
    data = np.empty(100, dtype='i')
comm.Bcast(data, root=0)
for i in range(100):
    assert data[i] == i

案例8:numpy的Scatter机制

from mpi4py import MPI
import numpy as np

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

sendbuf = None
if rank == 0:
    sendbuf = np.empty([size, 100], dtype='i')
    sendbuf.T[:,:] = range(size)
recvbuf = np.empty(100, dtype='i')
comm.Scatter(sendbuf, recvbuf, root=0)
assert np.allclose(recvbuf, rank)

案例9:numpy的Gather机制

from mpi4py import MPI
import numpy as np

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

sendbuf = np.zeros(100, dtype='i') + rank
recvbuf = None
if rank == 0:
    recvbuf = np.empty([size, 100], dtype='i')
comm.Gather(sendbuf, recvbuf, root=0)
if rank == 0:
    for i in range(size):
        assert np.allclose(recvbuf[i,:], i)

案例10 :allgather机制

Allgather操作可以理解为Scatter与广播的组合效果。假设rank0持有a,rank1持有b,rank2持有c,执行allgather后,每个进程都将获得完整的数据集:rank0 = a,b,c;rank1 = a,b,c;rank2 = a,b,c。

from mpi4py import MPI
import numpy

def matvec(comm, A, x):
    m = A.shape[0] # local rows
    p = comm.Get_size()
    xg = numpy.zeros(m*p, dtype='d')
    comm.Allgather([x,  MPI.DOUBLE],
                   [xg, MPI.DOUBLE])
    y = numpy.dot(A, xg)
    return y

到此这篇关于一文读懂python中mpi4py的所有基础使用的文章就介绍到这了,更多相关python mpi4py使用内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表