在单机条件下,MPI4PY与纯Python多进程代码来比较是否有性能优势???
如题:
最近在看MPI4PY的代码,但是发现这东西除了编写简洁外(少量代码实现复杂的多进程通信,包括单机和多机),好像也没有别的太多功能,当然MPI本身在多机通信广播、规约上做的很成熟,但是假设我们只是在一个单机上来运行Python多进程代码,那么使用MPI4PY除了代码简洁上以外在运行性能上是否会有区别呢???
本文探讨的主题就是如果我不使用分布式运行代码,而只是使用单机运行多进程代码,那么除了编码简洁外,MPI编程是否会有性能上的优势。
本文采用几个代码来探讨这个问题:本文代码为多子进程操作父进程中的一段内存,每次操作都将该内存中数据自加一。
给出第一个代码,纯Python实现,不使用MPI的情况下在单机运行多进程:
import ctypes
import time
import multiprocessing
import numpy as np #NUM_PROCESS = multiprocessing.cpu_count()
NUM_PROCESS = 4 size = 1000000 def worker(index):
main_nparray = np.frombuffer(shared_array_base[index], dtype=ctypes.c_double)
for i in range(10000):
main_nparray[:] = index + i
return index if __name__ == "__main__":
shared_array_base = []
for _ in range(NUM_PROCESS):
shared_array_base.append(multiprocessing.Array("d", size, lock=False)) pool = multiprocessing.Pool(processes=NUM_PROCESS) a = time.time()
result = pool.map(worker, range(NUM_PROCESS))
b = time.time()
print(b-a)
#print(result) for i in range(NUM_PROCESS):
main_nparray = np.frombuffer(shared_array_base[i], dtype=ctypes.c_double)
print(main_nparray)
print(type(main_nparray))
print(main_nparray.shape)
第二个代码,使用MPI4PY,多非root进程每一次操作都进行同步,root进程与非root进程通信采用分发和收集操作。
from mpi4py import MPI
import numpy as np
import time comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() recv_data = np.zeros(1000000, dtype=np.double) send_data = None
if rank == 0:
send_data = np.zeros((size, 1000000), dtype=np.double)
send_data[1]+=1
send_data[2]+=2
send_data[3]+=3 if rank ==0:
a=time.time()
for i in range(10000): comm.Scatter(send_data, recv_data, root=0) #if rank != 0:
# recv_data += 1
recv_data += 1 comm.Gather(recv_data, send_data, root=0)
if rank ==0:
b=time.time()
print(send_data)
print(b-a)
第三个代码,同样使用MPI4PY,多非root进程每一次操作都不进行同步,root进程与非root进程通信采用点对点方式,并且root进程与非root进程同样使用异步操作。
from mpi4py import MPI
import numpy as np
import time comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() recv_data = np.zeros(1000000, dtype=np.double) send_data = None
if rank == 0:
send_data = np.zeros((size-1, 1000000), dtype=np.double)
send_data[0]+=0
send_data[1]+=1
send_data[2]+=2
send_data[3]+=3 if rank == 0:
a, b, c, d = 10000, 10000, 10000, 10000
a_one_finish = True
b_one_finish = True
c_one_finish = True
d_one_finish = True a_time = time.time()
while True:
if a != 0:
if a_one_finish == True:
a_one_finish == False
a_req = comm.Isend(send_data[0], dest=1)
a_req2 = comm.Irecv(send_data[0], source=1)
a_one_finish = a_req2.test()[0]
if a_one_finish==True:
a -= 1
else:
a_one_finish = a_req2.test()[0]
if a_one_finish==True:
a -= 1 if b != 0:
if b_one_finish == True:
b_one_finish == False
b_req = comm.Isend(send_data[1], dest=2)
b_req2 = comm.Irecv(send_data[1], source=2)
b_one_finish = b_req2.test()[0]
if b_one_finish==True:
b -= 1
else:
b_one_finish = b_req2.test()[0]
if b_one_finish==True:
b -= 1 if c != 0:
if c_one_finish == True:
c_one_finish == False
c_req = comm.Isend(send_data[2], dest=3)
c_req2 = comm.Irecv(send_data[2], source=3)
c_one_finish = c_req2.test()[0]
if c_one_finish==True:
c -= 1
else:
c_one_finish = c_req2.test()[0]
if c_one_finish==True:
c -= 1 if d != 0:
if d_one_finish == True:
d_one_finish == False
d_req = comm.Isend(send_data[3], dest=4)
d_req2 = comm.Irecv(send_data[3], source=4)
d_one_finish = d_req2.test()[0]
if d_one_finish==True:
d -= 1
else:
d_one_finish = d_req2.test()[0]
if d_one_finish==True:
d -= 1 if a+b+c+d ==0:
break b_time = time.time()
print(b_time-a_time)
print(send_data) if rank != 0:
for _ in range(10000):
comm.Recv(recv_data, source=0)
recv_data += 1
comm.Send(recv_data, dest=0)
#print(recv_data)
注意:由于采用了点对点异步通信的方式,因此代码3中将总共运行的进程数些死了,只能运行5个进程,其中非root进程为4个。
===================================================
测试平台1:Xeon CPU: 24物理核心,48逻辑核心
代码1:运行时间:4.73 秒
代码2:运行时间:144.68 秒
代码3:运行时间:140.43 秒
测试平台2:i7 8代台式机CPU: 6物理核心,12逻辑核心
代码1:运行时间:16.05 秒
代码2:运行时间:80.61 秒
代码3:运行时间:84.24 秒
特别说明:
从上面的结果我们可以看到代码2的性能会比代码3的性能好一些,不过考虑到运行的误差性,我们可以把代码2与代码3的运行时间看做相当(几乎相同)。
其中,
代码2的运行命令为:mpirun -np 4 python x2.py
代码3的运行命令为:mpirun -np 5 python x3.py
在平台1上之所以代码1性能最好主要是因为在消息传递不是主要影响性能的因素时计算性能主要受向量计算能力所影响,而平台1的向量计算能力要优于平台2,因此平台1上代码1的性能最好。
平台1上之所以代码2,代码3的性能最差是因为当消息传统为性能主要影响因素时平台1的内存数据的传递速度要慢于平台2。
补充:共享内存的方式时多进程间消息传递几乎是不损耗时间的,几乎如在自身进程的内存空间中操作一样。
===================================================
从上面的计算结果可以推断出即使在单机情况下MPI编码的多进程通信也并不是采用共享内存的方式,而是进程间内存拷贝的方式,所以我们可以知道在单机情况下MPI编程的代码在消息传递方面并不占优势,只能说性能适合,其性能还是比不上手动编写的共享内存通信方式的性能。
呼应开篇之说,
本文探讨的主题就是如果我不使用分布式运行代码,而只是使用单机运行多进程代码,那么除了编码简洁外,MPI编程是否会有性能上的优势。
答案就是:
只使用单机运行多进程代码,那么除了编码简洁外(快速编程外),MPI编程并不会有性能上的优势。
总结一下:
MPI的优势:
使用MPI可以便捷的编写多进程代码,编写较为容易的将单进程代码改写为多进程代码。
或者说,MPI的优势是可以快速的在多机的分布式平台环境下运行,具有较好的扩充性,比较典型的应用场景就是在超算中心的超算平台上计算流体动力学这样的数值计算任务。比较MPI的代码可以很好的在上百台服务构成的计算环境中运行,而这种计算场景我们如果不使用MPI编程而是手动去编写代码去实现消息通信,那不仅工作量巨大,而且性能难以保证,甚至可能是一个不太可能实现的工作。
因此,如果你打算要你的代码(数值计算任务)以后在多机环境下(众多服务器环境,不太指那种两台,三台服务器环境)分布式运行那么MPI是你很好的选择,或者说是你唯一的选择,但是如果你就一台服务器,而且未来也不太可能有大集群服务器运行的可能,那么mpi编程并没有什么优势,或者说至少不是第一选择,也不是第二选择,或者说你不会别的并行通信方式的编码而只会mpi那么你选mpi编程完全OK。
参考:
https://materials.jeremybejarano.com/MPIwithPython/#
在单机条件下,MPI4PY与纯Python多进程代码来比较是否有性能优势???的更多相关文章
- 如何在已安装Python条件下,安装Anaconda,,并将原有Python添加到Anaconda中
在安装Anaconda之前,有的已经安装过一个Python版本了,但是又不想删除这个Python版本,该怎么办呢? 概括:轻松两步--在系统环境变量中找到对应之前安装Python的路径并删除:直接将你 ...
- 《Python CookBook2》 第四章 Python技巧 - 若列表中某元素存在则返回之 && 在无须共享引用的条件下创建列表的列表
若列表中某元素存在则返回之 任务: 你有一个列表L,还有一个索引号i,若i是有效索引时,返回L[i],若不是,则返回默认值v 解决方案: 列表支持双向索引,所以i可以为负数 >>> ...
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!
本文参考:http://www.dabeaz.com/coroutines/ 作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...
- 机器学习之线性回归(纯python实现)][转]
本文转载自:https://juejin.im/post/5a924df16fb9a0634514d6e1 机器学习之线性回归(纯python实现) 线性回归是机器学习中最基本的一个算法,大部分算法都 ...
- 虚拟机在 OpenStack 里没有共享存储条件下的在线迁移
虚拟机在 OpenStack 里没有共享存储条件下的在线迁移 本文尝试回答与 Live migration 相关的几个问题:Live migration 是什么?为什么要做 Live migratio ...
- 是AI就躲个飞机-纯Python实现人工智能
你要的答案或许都在这里:小鹏的博客目录 代码下载:Here. 很久以前微信流行过一个小游戏:打飞机,这个游戏简单又无聊.在2017年来临之际,我就实现一个超级弱智的人工智能(AI),这货可以躲避从屏幕 ...
- 纯python自研接口自动化脚本更新版本,让小白也能实现0到1万+的接口自动化用例
查看完整文章点击原文链接:纯python自研接口自动化脚本更新版本,让小白也能实现0到1万+的接口自动化用例 你是否还在用postman\jmeter做接口自动化吗?用python的开源框架[unit ...
- django之分页,纯python代码
Django中分页 py文件代码 """ 自定义分页组件 可以返回分页的数据和分页的HTML代码 """ from django.http ...
- 【Redis场景4】单机环境下秒杀问题
单机环境下的秒杀问题 全局唯一ID 为什么要使用全局唯一ID: 当用户抢购时,就会生成订单并保存到订单表中,而订单表如果使用数据库自增ID就存在一些问题: 受单表数据量的限制 id的规律性太明显 场景 ...
- 使用n2n在没有公网IP条件下访问树莓派
实现:在树莓派2和客户机都没有公网IP条件下实现远程访问控制 不足:暂时没实现网页代理 因为校园网环境没有公网IP,无法直接访问树莓派.之前有想过SSH反向代理:使用VPN,ddns(花生壳.no-i ...
随机推荐
- discuz论坛个人空间自定义css样式
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` discuz论坛个人空间自定义css样式 日期:2020- ...
- NetMvc通过亚马逊方式服务器端和客户端上传MinIO顺利解决
前言: 1.由于项目是.NET Framework 4.7 MVC LayUI,所以需要找一个资源站点存放项目中静态资源文件: 2.需要支持服务端和客户端都支持上传文件方式: 3.调用简单,涉及库越少 ...
- 13-nginx
关于nginx nginx是提供http服务的中间件. 这里推荐学习nginx的博客:朱双印的博客 安装 nginx的版本 主线版本(Mainline version) #最新版,不稳定 稳定版本(S ...
- Vim的移动大法
Vim的移动大法 移动光标的按键 "h" 向左移动 "j"向下移动 "k"向上移动 "l"向右移动 在单词之间移动 注: ...
- 背包dp——01背包
01背包是背包dp的基础的重点,重点的基础!!! 题意概要:有 n 个物品和一个容量为 W 的背包,每个物品有重量 w_{i} 和价值 v_{i} 两种属性,要求选若干物品放入背包使背包中物品的总价值 ...
- VulnHub_DC-4渗透流程
VulnHub_DC-4 DC-4 is another purposely built vulnerable lab with the intent of gaining experience in ...
- 从 Helm 到 Operator:Kubernetes应用管理的进化
Helm 的作用 在开始前需要先对 kubernetes Operator 有个简单的认识. 以为我们在编写部署一些简单 Deployment 的时候只需要自己编写一个 yaml 文件然后 kubec ...
- 谈谈你对 keep-alive 的了解?
在做电商有关的项目中,当我们第一次进入列表页需要请求一下数据,当我从列表页进入详情页,详情页不缓存也需要请求下数据,然后返回列表页,这时候我们使用keep-alive来缓存组件,防止二次渲染,这样会大 ...
- C#事件总结
前言:C#的事件也是一项非常关键的技术,必须要深刻的理解,本质上是基于委托的: 事件模型的五个组成部分: 1.事件的拥有者-- event source,对象: 2.事件的成员--event,成员: ...
- 解决方案 | onenote无法同步,显示:证书错误,应用程序在加载SSL库是遇到内部错误。
解决方案:一般是公司网络或者学校网络的问题,更换手机使用的数据流量热点无线网络即可.