接前文:

分享某Python下的mpi教程 —— A Python Introduction to Parallel Programming with MPI 1.0.2 documentation

https://materials.jeremybejarano.com/MPIwithPython/collectiveCom.html

Collective Communication

Reduce(…) and Allreduce(…)

例子:

Reduce

import numpy
from mpi4py import MPI comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() rankF = numpy.array(float(rank)) if rank == 0:
total = numpy.zeros(1)
else:
total = None comm.Reduce(rankF, total, op=MPI.MAX)
#comm.Reduce(rankF, total, op=MPI.SUM) if rank == 0:
print("total: ", total)

Allreduce

import numpy
from mpi4py import MPI comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() rankF = numpy.array(float(rank)) total = numpy.zeros(1) comm.Allreduce(rankF, total, op=MPI.MAX) print("rank {} : total {} ".format(rank, total))

Scatter

# dotProductParallel_1.py
# "to run" syntax example: mpiexec -n 4 python26 dotProductParallel_1.py 40000
from mpi4py import MPI
import numpy
import sys comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() # read from command line
# n = int(sys.argv[1]) #length of vectors
n = 10000 # arbitrary example vectors, generated to be evenly divided by the number of
# processes for convenience x = numpy.linspace(0, 100, n) if comm.rank == 0 else None
y = numpy.linspace(20, 300, n) if comm.rank == 0 else None # initialize as numpy arrays
dot = numpy.array([0.])
local_n = numpy.array([0], dtype=numpy.int32) # test for conformability
if rank == 0:
if n != y.size:
print("vector length mismatch")
comm.Abort() # currently, our program cannot handle sizes that are not evenly divided by
# the number of processors
if n % size != 0:
print("the number of processors must evenly divide n.")
comm.Abort() # length of each process's portion of the original vector
local_n = numpy.array([n / size], dtype=numpy.int32) # communicate local array size to all processes
comm.Bcast(local_n, root=0) # initialize as numpy arrays
local_x = numpy.zeros(local_n)
local_y = numpy.zeros(local_n) # divide up vectors
comm.Scatter(x, local_x, root=0)
comm.Scatter(y, local_y, root=0) # local computation of dot product
local_dot = numpy.array([numpy.dot(local_x, local_y)]) # sum the results of each
#comm.Reduce(local_dot, dot, op=MPI.SUM)
comm.Allreduce(local_dot, dot, op=MPI.SUM) print("The dot product is", dot[0], "computed in parallel") if rank == 0:
#print("The dot product is", dot[0], "computed in parallel")
print("and", numpy.dot(x, y), "computed serially")

Scatterv(…) and Gatherv(…)

# for correct performance, run unbuffered with 3 processes:
# mpiexec -n 3 python26 scratch.py -u
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank() if rank == 0:
x_global = numpy.linspace(0,100,11)
else:
x_global = None if rank == 0:
x_local = numpy.zeros(1)
elif rank == 1:
x_local = numpy.zeros(1)
elif rank == 2:
x_local = numpy.zeros(9) if rank == 0:
print("Scatter") comm.Scatterv([x_global, (1,1,9), (0,1,2), MPI.DOUBLE], x_local)
print("process " + str(rank) + " has " + str(x_local)) comm.Barrier() if rank == 0:
print("Gather")
xGathered = numpy.zeros(11)
else:
xGathered = None comm.Gatherv(x_local, [xGathered, (1,1,9), (0,1,2), MPI.DOUBLE]) print("process " + str(rank) + " has " +str(xGathered))

该代码运行命令为:

mpiexec -np 3 python x.py

上个代码有个地方容易被忽视那就是  函数  comm.Scatterv  其实是非堵塞的,也就是说如果rank==0进程在执行该语句后不进行同步操作:comm.Barrier

那么rank==0进程会继续向下执行而不会等待rank==1,rank==2进程完全接收数据到各自的变量  x_local  中。

给出修改的代码:

# for correct performance, run unbuffered with 3 processes:
# mpiexec -n 3 python26 scratch.py -u
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank() if rank == 0:
x_global = numpy.linspace(0,100,11)
else:
x_global = None if rank == 0:
x_local = numpy.zeros(1)
elif rank == 1:
x_local = numpy.zeros(1)
elif rank == 2:
x_local = numpy.zeros(9) if rank == 0:
print("Scatter") if rank != 0:
import time
time.sleep(10) comm.Scatterv([x_global, (1,1,9), (0,1,2), MPI.DOUBLE], x_local)
print("process " + str(rank) + " has " + str(x_local)) #comm.Barrier() if rank == 0:
print("Gather")
xGathered = numpy.zeros(11)
else:
xGathered = None comm.Gatherv(x_local, [xGathered, (1,1,9), (0,1,2), MPI.DOUBLE]) print("process " + str(rank) + " has " +str(xGathered))

该代码执行后会先打印结果:

Scatter
process 0 has [0.]
Gather

然后进入堵塞大致10秒时间,由此可以看到不进行 comm.Barrier 操作的 comm.Scatterv 是非堵塞的,rank==0没有等待其他进程完全接收数据便向下执行了,但是从运行结果上我们可以看到收集操作 comm.Gatherv  是堵塞的,也正因此rank==0进程会在此处进入堵塞10秒的状态。

由于上面的代码后续运行中有堵塞操作了,因此没有 comm.Barrier 操作也不会有问题,不过对于MPI中的非堵塞操作还是进行同步操作 comm.Barrier 操作以防万一的安全一些。

该代码运行命令同样也为:

mpiexec -np 3 python x.py

==================================================

上面的代码其实是把进程数量硬编码进入代码里面了,如果运行不是 -np 3 而是其他数值则会报错,而这种编码方式是不妥的,因此不把进程数硬编码进去同时也能实现很好的计算负载是需要的。给出自己的工作:

实现计算负载均衡的代码:

# for correct performance, run unbuffered with 3 processes:
# mpiexec -n 3 python26 scratch.py -u
import numpy
from mpi4py import MPI comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size() n = 10000
if rank == 0:
x_global = numpy.linspace(0,100,n)
else:
x_global = None n_local = numpy.zeros(size, dtype=numpy.int32)
n_local[:] = n // size
if n%size != 0:
n_local[-(n%size):] += 1 begin_local = numpy.zeros(size)
for i in range(1, size):
begin_local[i] = begin_local[i-1] + n_local[i-1] x_local = numpy.zeros(n_local[rank]) #if rank != 0:
# import time
# time.sleep(5)
if rank == 0:
print("Scatter") comm.Scatterv([x_global, n_local, begin_local, MPI.DOUBLE], x_local)
print("process " + str(rank) + " has " + str(x_local[:5])) comm.Barrier() if rank == 0:
print("Gather")
xGathered = numpy.zeros(n)
else:
xGathered = None comm.Gatherv(x_local, [xGathered, n_local, begin_local, MPI.DOUBLE]) print("process " + str(rank) + " has " +str(xGathered))

运行命令:

mpiexec -np 23 python  x.py

可以看到改进后的代码没有把总共运行的进程数硬编码到代码中,而是可以根据实际需要对任意数值下的总进程数实现计算负载均衡。改进代码根据总的运行进程数将计算服务均衡的划分给所有计算进程。

================================================

以上代码运行命令如无特殊说明则为:

mpiexec -np 8 python x.py

分享某Python下的mpi教程 —— A Python Introduction to Parallel Programming with MPI 1.0.2 documentation ( 续 #2 )的更多相关文章

  1. Python学习入门基础教程(learning Python)--5.6 Python读文件操作高级

    前文5.2节和5.4节分别就Python下读文件操作做了基础性讲述和提升性介绍,但是仍有些问题,比如在5.4节里涉及到一个多次读文件的问题,实际上我们还没有完全阐述完毕,下面这个图片的问题在哪呢? 问 ...

  2. Python学习入门基础教程(learning Python)--5.1 Python下文件处理基本过程

    Python下的文件读写操作过程和其他高级语言如C语言的操作过程基本一致,都要经历以下几个基本过程. 1. 打开文件 首先是要打开文件,打开文件的主要目的是为了建立程序和文件之间的联系.按程序访问文件 ...

  3. Python学习入门基础教程(learning Python)--5.2 Python读文件基础

    上节简单的说明了一下Pyhon下的文件读写基本流程,从本节开始,我们做几个小例子来具体展示一下Python下的文件操作,本节主要是详细讲述Python的文件读操作. 下面举一个例子,例子的功能是读取当 ...

  4. Python学习入门基础教程(learning Python)--5 Python文件处理

    本节主要讨论Python下的文件操作技术. 首先,要明白为何要学习或者说关系文件操作这件事?其实道理很简单,Python程序运行时,数据是存放在RAM里的,当Python程序运行结束后数据从RAM被清 ...

  5. Python学习入门基础教程(learning Python)--5.3 Python写文件基础

    前边我们学习了一下Python下如何读取一个文件的基本操作,学会了read和readline两个函数,本节我们学习一下Python下写文件的基本操作方法. 这里仍然是举例来说明如何写文件.例子的功能是 ...

  6. Python学习入门基础教程(learning Python)--3.1Python的if分支语句

    本节研究一下if分支语句. if分支语句是Python下逻辑条件控制语句,用于条件执行某些语句的控制操作,当if后的条件conditon满足时,if其下的语句块被执行,但当if的控制条件condito ...

  7. Python学习入门基础教程(learning Python)--6.3 Python的list切片高级

    上节"6.2 Python的list访问索引和切片"主要学习了Python下的List的访问技术:索引和切片的基础知识,这节将就List的索引index和切片Slice知识点做进一 ...

  8. Python学习入门基础教程(learning Python)--6.4 Python的list与函数

    list是python下的一种数据类型,他和其他类型如整形.浮点型.字符串等数据类型一样也可作为函数的型参和实参来使用! 1.list作为参数 list数据类型可以作为函数的参数传递给函数取做相应的处 ...

  9. Python学习入门基础教程(learning Python)--5.7 Python文件数据记录存储与处理

    本节主要讨论Python下如何通过文件操作实现对数据记录集的存储与处理的操作方法. 在Python里和其他高级语言一样可以通过文件读写将一些记录集写入文件或者通过文件读操作从文件里读取一条或多条和数据 ...

  10. Python学习入门基础教程(learning Python)--2.3.3Python函数型参详解

    本节讨论Python下函数型参的预设值问题. Python在设计函数时,可以给型参预设缺省值,当用户调用函数时可以不输入实参.如果用户不想使用缺省预设值则需要给型参一一赋值,可以给某些型参赋值或不按型 ...

随机推荐

  1. EF EntityFramework 强制从数据库中取数据,而不是上下文

    场景:插入了一条数据到数据库,这条数据会有其它程序修改,接着程序想获取最新数据.此时不加额外处理,取的仍是旧的. t_task ta = new t_task(); ta.item_id = item ...

  2. C#.NET 国密 SM2 公钥证书从文本转换

    先前的 Util 是直接从文件中转换的 https://www.cnblogs.com/runliuv/p/15079404.html public static AsymmetricKeyParam ...

  3. 小白也能玩转Git:从入门到实战详细教程

    Git介绍 Git是一种分布式版本控制系统,它广泛应用于软件开发中.通过Git,开发人员可以追踪文件的变化.协作工作.管理代码库等.与集中式版本控制系统(如SVN)不同,Git使每个开发人员都具有完整 ...

  4. 记一下 localstorage sessionStorage cookie 不同

    localStorage.sessionStorage.cookie 使用整理 下面从这几方面进行梳理 存储形式 相同点 不同点 使用方法 用途 多标签之间通讯 一.存储形式 1.localStron ...

  5. 开箱即用的Live2d

    安装 npm i @tomiaa/live2d 代码 <template> <div ref="live2dContentRef" id="live2d ...

  6. 深入理解Android View(1)

    做android其实也有一段时间了,我们每个人都会碰到一些这样或那样的问题,碰到问题了就拼命百度,可是发现,我们解决问题的能力并没有提升很多,所以我才有想总结一下我项目中所用过的相关知识,并了解一下A ...

  7. 算法金 | A - Z,115 个数据科学 机器学习 江湖黑话(全面)

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 机器学习本质上和数据科学一样都是依赖概率统计,今天整整那些听起来让人头大的机器学习江湖 ...

  8. 基恩士PLC数据 转 Modbus RTU TCP项目案例

    1         案例说明 1.   设置网关采集基恩士PLC数据 2.   把采集的数据转成Modbus协议转发给其他系统. var code = "244226f8-1eed-48e4 ...

  9. 从零开始带你上手体验Sermant自定义插件开发

    本文分享自华为云社区<Sermant自定义插件开发上手体验>,作者:华为云开源. 一.研究缘由 由于目前我们所处的行业是汽车行业,项目上进行云服务的迁移时使用到了Sermant中的相关插件 ...

  10. throws和try catch的区别

    1.throws是表明方法抛出异常,需要调用者来处理,如果不想处理就一直向外抛,最后会有jvm来处理: 2.try catch 是自己来捕获别人抛出的异常,然后在catch里面去处理: 一般情况下,第 ...