版权声明:本文为博主原创文章,未经博主允许不得转载。

1.概述

MPI(Message Passing Interface),消息传递接口,是一个标准化和轻便的能够运行在各种各样并行计算机上的消息传递系统。消息传递指的是并行执行的各个进程拥有自己独立的堆栈和代码段,作为互不相关的多个程序独立执行,进程之间的信息交互完全通过显示地调用通信函数来完成。

mpi4py是构建在MPI之上的Python非官方库,使得Python的数据可以在进程之间进行传递。

2.MPI执行模型

并行程序是指一组独立、同一的处理过程;

  • 所有的进程包含相同的代码;

  • 进程可以在不同的节点或者不同的计算机;

  • 当使用Python,使用n个Python解释器;

    mpirun -np 32 python parallel_script.py

并行执行模型如下所示,

2.1 MPI基本概念

rank:给予每个进程的id;

  • 可通过rank进行查询;
  • 根据rank,进程可以执行不同的任务;

Communicator:包含进程的群组;

  • mpi4py中基本的对象,通过它来调用方法;
  • MPI_COMM_WORLD,包含所有的进程(mpi4py中是MPI.COMM_WORLD);

2.2 数据模型

所有的变量和数据结构都是进程的局部值;

进程之间通过发送和接收消息来交换数据;

2.3 使用mpi4py

from mpi4py import MPI
comm = MPI.COMM_WORLD #Communicator对象包含所有进程
size = comm.Get_size()
rank = comm.Get_rank()
print "rank = %d,size = %d"%(rank,size)

2.4 安装mpi4py

MPI Python环境搭建

MPI Windows集群环境搭建

3.工作方式

工作方式主要有点对点和群体通信两种;点对点通信就是一对一,群体通信是一对多;

3.1 点对点

example 1

点对点发送Python内置dict对象;

#Broadcasting a Python dict
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)
print "send data = ",data
elif rank == 1:
data = comm.recv(source = 0,tag = 11)
print "recv data = ",data

任意的Python内置对象可以通过send和recv进行通信,目标rank和源rank和tag都要互相匹配;

send(data,dest,tag)

  • data,待发送的Python内置对象;
  • dest,目标rank;
  • tag,发送消息的id;

recv(source,tag)

  • source,源rank;
  • tag,发送消息的id;

example 2

点对点发送Python内置dict对象,非阻塞通信;

#point to point communication Python objects with non-blocking communication
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()
print "send data = ",data
elif rank == 1:
req = comm.irecv(source = 0,tag = 11)
data = req.wait()
print "recv data = ",data

example 3

发送Numpy数组;

#point to point communication Python objects Numpy arrays
from mpi4py import MPI
import numpy as np comm = MPI.COMM_WORLD
rank = comm.Get_rank() # automatic MPI datatypes discovery
if rank == 0:
data = np.arange(100,dtype = np.int)
comm.Send(data, dest = 1,tag = 13)
print "send data = ",data
elif rank == 1:
data = np.empty(100,dtype = np.int)
comm.Recv(data, source = 0,tag = 13)
print "recv data = ",data

当发送消息时,任意的Python对象转换为字节流;

当接收消息时,字节流被转换为Python对象;

Send(data,dest,tag),Recv(data,source,tag),连续型数组,速度快;

send(data,dest,tag),recv(source,tag),Python内置对象,速度慢;

3.2 群体通信

群体通信分为发送和接收,发送是一次性把数据发给所有人,接收是一次性从所有人那里回收结果;

example 1

root进程新建data dict,然后将data数据广播给所有的进程,这样所有的进程都拥有这个data dict;

#Broadcasting a Python dict
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)
print "rank = ",rank," data = ",data

example 2

root进程新建了一个list,然后将它散播给所有的进程,相当于对这个list做了划分,每个进程获得等分的数据,这里就是list中的每一个数字(主要根据list的索引来划分,list索引为第i份的数据就发送给第i个进程),如果是矩阵,那么久等分的划分行,每个进程获得相同的行数进行处理;

MPI的工作方式是每个进程都会执行所有的代码,每个进程都会执行scatter这个指令,但是只有root进程执行它的时候,它才兼备发送者和接收者的身份(root进程也会得到数据它自己的那份数据),对于其他进程来说,他们都只是接收者而已;

#Scattering Python objects
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
print "rank = ",rank," data = ",data

example 3

gather是将所有进程的数据收集回来,然后合并成一个列表;

#Gathering Python objects
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)
print "data = ",data
else:
assert data is None

example 4

广播Numpy数组;

#Broadcasting Numpy array
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)
print "rank = ",rank," data = ",data

example 5

散播Numpy数组;

#Scattering Numpy arrays
from mpi4py import MPI
import numpy as np comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank() senbuf = None
if rank == 0:
senbuf = np.empty([size,100],dtype = 'i')
senbuf.T[:,:] = range(size)
recvbuf = np.empty(100,dtype = 'i')
comm.Scatter(senbuf,recvbuf,root = 0)
assert np.allclose(recvbuf,rank)
print "rank = ",rank," recvbuf = ",recvbuf

example 6

收集Numpy数组;

#Gathering Numpy array
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)

4.Reference

mpi4py tutorial

Python多核编程mpi4py实践

mpi4py实践的更多相关文章

  1. Python多核编程mpi4py实践及并行计算-环境搭建篇

    1.安装python,这个没什好说的,直接装就行 2.做并行计算.数据挖掘,机器学习等一般都要用的numpy,这个在Windows版本上安装有点问题,安装比较麻烦,建议在linux上搭建环境 3.安装 ...

  2. Python 高性能并行计算之 mpi4py

    MPI  和    MPI4PY   的搭建上一篇文章已经介绍,这里面介绍一些基本用法. mpi4py  的  helloworld from mpi4py import MPI print(&quo ...

  3. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  4. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  5. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  6. Logstash实践: 分布式系统的日志监控

    文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...

  7. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

  8. Windows平台分布式架构实践 - 负载均衡

    概述 最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行.那么大家(开发者和企业)为 ...

  9. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

随机推荐

  1. Android 利用RecyclerView.Adapter刷新列表中的单个view问题

    首先使用RecyclerView的adapter继承:RecyclerView.Adapter public class OrderListAdapter extends RecyclerView.A ...

  2. css 浅析display属性

    继续开始我的css之旅吧.今天我们来说什么啊.构思了两天还是没有什么思路,但是学习的步伐我们不能停止下来.还是按照之前的计划来讲讲display,在讲这个之前我们还是按照老规矩来扯扯蛋,步子不能够迈大 ...

  3. weex scroller

    今天学习了一下weex的 scroller.就简单地对其整理一下自己的学习笔记. <scroller>这个标签只能出现在列(column)上面, 只有当它自己的内容大于类似与PC父级的高度 ...

  4. JS 将数字转化成为货币格式

    最近由于项目的需要需要将数字format成货币格式,自己搞了半天效果不是很好,博客园有篇问题很好,再次转载记录一下 http://www.cnblogs.com/mingmingruyuedlut/a ...

  5. eclipse导入项目出现叹号处理方法:

    1.选中该项目名称,单击右键 2.点击Properties 3.选中Java Build Path 4. 5. 6. 7.出现红叉的解决办法 8. 9. 10. 11. 12. 按照以上步骤操作就可以 ...

  6. cocoapods安装出错问题

    今天执行pod install时,出现了错误,提示更新,好,那就更新; 1.终端执行了下:gem sources -l   查看了下源 *** CURRENT SOURCES *** https:// ...

  7. bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)

    题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...

  8. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

  9. 深入理解OAuth2.0协议

    1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...

  10. MYSQL删除重复数据

     delete from co_jobinformation cwhere c.name in (select cc.name from co_jobinformation cc group by   ...