python mpi4py_Python多核编程mpi4py实践

编辑推荐:本文来源于csdn,介绍了MPI与mpi4py,常见用法,MPI和mpi4py的环境搭建等知识。一、概述CPU从三十多年前的8086,到十年前的奔腾,再到当下的多核i7。一开始,以单核cpu的主频为目标,架构的改良和集成电路工艺的进步使得cpu的性能高速上升,单核cpu的主频从老爷车的MHz阶段一度接近4GHz高地。然而,也因为工艺和功耗等的限制,单核cpu遇到了人生的天花板,急需转换思...
摘要由CSDN通过智能技术生成

编辑推荐:

本文来源于csdn,介绍了MPI与mpi4py,常见用法,MPI和mpi4py的环境搭建等知识。

一、概述

CPU从三十多年前的8086,到十年前的奔腾,再到当下的多核i7。一开始,以单核cpu的主频为目标,架构的改良和集成电路工艺的进步使得cpu的性能高速上升,单核cpu的主频从老爷车的MHz阶段一度接近4GHz高地。然而,也因为工艺和功耗等的限制,单核cpu遇到了人生的天花板,急需转换思维,以满足无止境的性能需求。多核cpu在此登上历史舞台。给你的老爷车多加两个引擎,让你有法拉利的感觉。现时代,连手机都到处叫嚣自己有4核8核处理器的时代,PC就更不用说了。

扯远了,anyway,对于俺们程序员来说,如何利用如此强大的引擎完成我们的任务才是我们要考虑的。随着大规模数据处理、大规模问题和复杂系统求解需求的增加,以前的单核编程已经有心无力了。如果程序一跑就得几个小时,甚至一天,想想都无法原谅自己。那如何让自己更快的过度到高大上的多核并行编程中去呢?哈哈,广大人民的力量!

目前工作中我所接触到的并行处理框架主要有MPI、OpenMP和MapReduce(Hadoop)三个(CUDA属于GPU并行编程,这里不提及)。MPI和Hadoop都可以在集群中运行,而OpenMP因为共享存储结构的关系,不能在集群上运行,只能单机。另外,MPI可以让数据保留在内存中,可以为节点间的通信和数据交互保存上下文,所以能执行迭代算法,而Hadoop却不具有这个特性。因此,需要迭代的机器学习算法大多使用MPI来实现。当然了,部分机器学习算法也是可以通过设计使用Hadoop来完成的。(浅见,如果错误,希望各位不吝指出,谢谢)。

本文主要介绍Python环境下MPI编程的实践基础。

二、MPI与mpi4py

MPI是Message Passing Interface的简称,也就是消息传递。消息传递指的是并行执行的各个进程具有自己独立的堆栈和代码段,作为互不相关的多个程序独立执行,进程之间的信息交互完全通过显示地调用通信函数来完成。

Mpi4py是构建在mpi之上的python库,使得python的数据结构可以在进程(或者多个cpu)之间进行传递。

2.1、MPI的工作方式

很简单,就是你启动了一组MPI进程,每个进程都是执行同样的代码!然后每个进程都有一个ID,也就是rank来标记我是谁。什么意思呢?假设一个CPU是你请的一个工人,共有10个工人。你有100块砖头要搬,然后很公平,让每个工人搬10块。这时候,你把任务写到一个任务卡里面,让10个工人都执行这个任务卡中的任务,也就是搬砖!这个任务卡中的“搬砖”就是你写的代码。然后10个CPU执行同一段代码。需要注意的是,代码里面的所有变量都是每个进程独有的,虽然名字相同。

例如,一个脚本test.py,里面包含以下代码:

from mpi4py import MPI

print("hello world'')

print("my rank is: %d" %MPI.rank)

然后我们在命令行通过以下方式运行:

#mpirun –np 5 python test.py

-np5 指定启动5个mpi进程来执行后面的程序。相当于对脚本拷贝了5份,每个进程运行一份,互不干扰。在运行的时候代码里面唯一的不同,就是各自的rank也就是ID不一样。所以这个代码就会打印5个hello

world和5个不同的rank值,从0到4.

2.2、点对点通信

点对点通信(Point-to-PointCommunication)的能力是信息传递系统最基本的要求。意思就是让两个进程直接可以传输数据,也就是一个发送数据,另一个接收数据。接口就两个,send和recv,来个例子:

import mpi4py.MPI

as MPI

comm = MPI.COMM_WORLD

comm_rank = comm.Get_rank()

comm_size = comm.Get_size()

# point to point communication

data_send = [comm_rank]*5

comm.send(data_send,dest=(comm_rank+1)%comm_size)

data_recv =comm.recv(source=(comm_rank-1)%comm_size)

print("my rank is %d, and Ireceived:"

% comm_rank)

print data_recv

启动5个进程运行以上代码,结果如下:

my rank is 0, and I received:

[4, 4, 4, 4, 4]

my rank is 1, and I received:

[0, 0, 0, 0, 0]

my rank is 2, and I received:

[1, 1, 1, 1, 1]

my rank is 3, and I received:

[2, 2, 2, 2, 2]

my rank is 4, and I received:

[3, 3, 3, 3, 3]

可以看到,每个进程都创建了一个数组,然后把它传递给下一个进程,最后的那个进程传递给第一个进程。comm_size就是mpi的进程个数,也就是-np指定的那个数。MPI.COMM_WORLD

表示进程所在的通信组。

但这里面有个需要注意的问题,如果我们要发送的数据比较小的话,mpi会缓存我们的数据,也就是说执行到send这个代码的时候,会缓存被send的数据,然后继续执行后面的指令,而不会等待对方进程执行recv指令接收完这个数据。但是,如果要发送的数据很大,那么进程就是挂起等待,直到接收进程执行了recv指令接收了这个数据,进程才继续往下执行。所以上述的代码发送[rank]*5没啥问题,如果发送[rank]*500程序就会半死不活的样子了。因为所有的

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值