并行for循环,简单的改动让python飞起来

news2024/11/20 13:44:51

 

概要

Python在处理大的数据集的时候总是速度感人。代码一旦开始运行,剩下的时间只好满心愧疚地刷手机。

 

MPI(Message Passing Interface)是在并行计算中,在不同进程间传递信息的标准解决方案。mpi4py是它的python版本。

网上有大量教程讲怎么通过mpi4py实现同步运行相对独立的python代码。在服务器上跑代码的时候尤其有用。

在正式开始之前,有两个基本概念需要理解:

node,翻译一般作服务器节点。我的理解,一个node,可以看作是一台个人电脑。每个node(每台电脑)可以有多个core(核)。比如你可能听过,一个程序在12个nodes上运行,每个nodes运行128个任务。就是说,这个程序同步运行在个cores上。可能一个core还可以有多个CPU.

比如下面展示的简单示例中,一共有12个并行任务。我们让它在2个nodes上运行,所以每个nodes需要运行6个任务。同时我们指定每个node只调用4个cores(因为所有的cores平分memory,如果一次性调用所有的cores,每个core能用的memory可能不够单个任务所需)。这样的话,6个任务分配到4个核,有些核需要跑两遍,比如[2,2,1,1]。参考下图。

 

d16312e6b7fa478289e54fd08bee62b0.png

要让python代码通过mpi4py并行,实际上需要改动的地方并不多。基本的逻辑是,从系统中拿到所有node和所有core的index,这样就得到可以同步运算的所有“通道”的index,然后根据“通道”总数量,将需要运行的任务分成多个组,最后将不同的组分配到不同的“通道”上单独运行即可。

1. 修改python代码以支持mpi4py

假设你想要并行运算的python代码叫“python_mpi4py.py“,这个代码是一个可以独立在一台电脑上(一个node)上执行的代码。下面的解释只为增加理解(可以略过),实际上代码读懂了改的地方不多。

  • 参数num指定这个python的主体代码运行在哪个node上。实际上只用于输出信息之用。

  • 参数t1t2指定,在所有的任务中,当前的node上(node index 为num)运行第t1-t2步。我们总共有12步 (代码中periods=12)的任务,且我们指定两个node运行这12步任务,所以当前node只跑所有任务中的一部分(第t1-t2步)。因为调用2个nodes,python_mpi4py.py会被运行2次,每次接受不同的t1t2,两步加起来就运行了所有的t。

  • ranksize是mpi4py中很重要的概念。现在我们回到单个node,这里的rank可以看作是这个node中所有core的index。比如,我们指定调用4个cores,那rank的值就是一个listrank=[0,1,2,3]size(代码中写作npro)是获得的cores的总数,这里size=4。这里的解释肯定是过度简单化了。但大概这样。

  • 然后就是前面提到的分组。尽管这个node得到的已经是一个sub- group(只有steps_global[t1:t2])。这个sub- group还需要进一步分给不同的cores(代码中的list_all_pros ).

  • 然后各个core会同时进行,但是,我们在每个核上有不止一个任务([2,2,1,1]),所以要进行唯一的循环。

#%%
import sys
import numpy as np
import mpi4py
import time as pytime
import pandas as pd

# get the number of the node, and the range of the steps [t1:t2] that runs on this node 
num = int(sys.argv[1])
t1 = int(sys.argv[2])
t2 = int(sys.argv[3])

# example of all the steps that need to be run on all the nodes
time = pd.date_range('2020-01-01', periods=12, freq='H')

# the steps that need to be run on this node
steps_global = np.arange(time.size)
steps = steps_global[t1:t2] # sub-group for this node

# === mpi4py ===
try:
  from mpi4py import MPI
  comm = MPI.COMM_WORLD
  rank = comm.Get_rank()
  npro = comm.Get_size()
except:
  print('::: Warning: Proceeding without mpi4py! :::')
  rank = 0
  npro = 1


list_all_pros = [0]*npro # sub-sub-groups for all the cores
for nn in range(npro):
  list_all_pros[nn] = steps[nn::npro]
steps = list_all_pros[rank]

pytime.sleep(0.1*rank) # to make sure the print statements are in order

# use mpi4py here
for kk, step in enumerate(steps):
  print(f'node: {num}: kk = {kk+1}/{steps.size}, step = {step}')
  print(f'{time[step]}')

上面的代码,我们把原本要进行的12步循环,最后压缩到了最大2步循环。当然,这个想象空间还是很大的。

2. 在单个node上运行python代码

要运行上面的包含mpi4py的代码,最简单的可以一句bash命令就可以:

mpirun -np 4 python -u python_mpi4py.py $1 $2 $3

上面命令-np 4指定4个核同时运行。然后$1指定node的index,$2$3分别指定在这个node上面运行的步骤的index。

当然服务器上,一般要先allocate 资源,然后写一个脚本(命名为submit_python_mpi4py.sh)提交后台运行代码:

#!/bin/bash
#SBATCH --job-name=parallel
#SBATCH --time=00:01:00
#SBATCH --partition=compute
#SBATCH --nodes=1
#SBATCH --ntasks=4
#SBATCH --account=*****

mpirun -np 4 python -u python_mpi4py.py $1 $2 $3

3. 在多个node上运行python代码

为了好理解,这里通过一个python代码多次提交上面的bash代码,即申请多个node。这样做可以更加直接得控制哪些任务运行在哪个node上。比如,让不同的模型在不同的nodes上运行。这个python文件我们命名为master_submitter.py

#!/usr/bin/env python
#%%
import os
import numpy as np

#%%
nsteps = 12
npar   = 6
njobs  = int(nsteps/npar) # 2 nodes


#%%
for kk in range(njobs): #0,1 node-index
  k1 = kk*npar #0,6 the starting task-index for node1 and node2
  k2 = (kk+1)*npar #6,12 the ending task-index for node1 and node2
  print("-----node line -----")
  os.system(f"sbatch ./submit_python_mpi4py.sh {kk+1} {k1} {k2}") # 
# %%

上面的示例简单展示了一种可以利用mpi4py在多个nodes,多个cores上并行运算的例子。上面的例子中,各个任务之间是完全没有依赖的。但是我们的for循环结束了之后一般比如会有个concat操作之类的,需要将各个cores运行的结果收集起来。mpi4py也支持在不同的任务之间传输数据。更多信息网上找啦。

 

今天的分享就到这,欢迎点赞收藏转发,感谢🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/830393.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenUSD联盟:塑造元宇宙的3D未来

一、引言 近日,美国3D内容行业的五家主要公司苹果、英伟达、皮克斯、Adobe和Autodesk联合成立了OpenUSD联盟(AOUSD)。这一联盟的成立标志着元宇宙领域的一次重要合作,旨在制定元宇宙的3D图形标准。本文将深入探讨OpenUSD联盟的目…

配置NFS,遇到的问题总结(电脑连接WiFi,开发板和电脑直连)

我使用的正点原子的方法,仅展示遇到的问题。 1. 这一步,需要先将Ubuntu关掉,再进行设置。 如果设置了不显示,需要移出网络,再次添加。 先设置Windows的网络,再设置,虚拟机的网络,即…

idea运行web老项目

idea打开老项目 首先你要用idea打开老项目,这里看我之前发的文章就可以啦 运行web项目 1. 编辑配置 2. 添加tomcat项目 3. 设置tomcat参数 选择本地tomcat,注意有的tomcat版本,不然运行不了设置-Dfile.encodingUTF-8 启动,注意…

[openCV]基于拟合中线的智能车巡线方案V3

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表"""newDir d…

kafka 理论知识

1 首先要了解kafka是什么 Kafka是一个分布式的消息订阅系统 1.1 kafka存储消息的过程 消息被持久化到一个topic中,topic是按照“主题名-分区”存储的,一个topic可以分为多个partition,在parition(分区)内的每条消息都有一个有序的id号&am…

【基础类】—三栏页面布局的方案和优缺点

一、假设高度已知&#xff0c;中间宽度自适应&#xff0c;三栏&#xff08;列&#xff09;布局的方案有哪些&#xff1f; float浮动、absolute绝对定位、flex弹性盒子、table表格布局、grid网格布局 浮动 float <style>* {margin: 0;padding: 0;}.container {width: 1…

Stable Diffusion 硬核生存指南:WebUI 中的 CodeFormer

本篇文章聊聊 Stable Diffusion WebUI 中的核心组件&#xff0c;强壮的人脸图像面部画面修复模型 CodeFormer 相关的事情。 写在前面 在 Stable Diffusion WebUI 项目中&#xff0c;源码 modules 目录中&#xff0c;有一个有趣的目录叫做 CodeFormer&#xff0c;它就是本文的…

Vue2 第十六节 $nextTick 和 动画与过渡效果

1. $nextTick 2.过渡与动画 一. $nextTick ① 语法&#xff1a;this.$nextTick(回调函数) ② 作用&#xff1a;在下一次DOM更新结束后执行其指定的回调 nextTick所指定的回调会在DOM节点更新后执行 ③ 使用场景&#xff1a;当改变数据后&#xff0c;要基于更新后的新 DOM …

ClickHouse(十):Clickhouse表引擎 - Special系列表引擎

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…

ad+硬件每日学习十个知识点(19)23.7.30 (LDO参数介绍)

文章目录 1.LDO的压差dropout2.线性调整率&#xff08;输入变化对输出的影响&#xff09;3.负载调整率&#xff08;负载变化对输出电压的影响&#xff09;4.纹波抑制比PSRR&#xff08;电源抑制比&#xff09;5.哪些元器件对PSRR影响大&#xff1f;&#xff08;右下角图&#x…

算法通过村——Hash和队列问题解析

算法的备胎Hash和找靠山的队列 备胎Hash Hash&#xff0c;不管是算法&#xff0c;还是在工程中都会大量使用。很多复杂的算法问题都用Hash能够轻松解决&#xff0c;也正是如此&#xff0c;在算法例就显得没什么思维含量&#xff0c;所以Hash是应用里的扛把子&#xff0c;但在算…

Flink State 和 Fault Tolerance详解

有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态&#xff0c;这就使得状态在整个Flink的精细化计算中有着非常重要的地位&#xff1a; 记录数据从某一个过去时间点到当前时间的状态信息。以每分钟/小时/天汇总事件时&#xff0c;状态将保留…

录屏功能怎么录声音?这些方法都能很好的录制

在现代社交媒体的时代&#xff0c;录制视频已成为了人们记录生活和分享经验的重要方式之一。而在录制视频的过程中&#xff0c;声音也是至关重要的一个方面。因此&#xff0c;在手机上使用录屏功能时&#xff0c;如何录制声音成为了一个常见的问题。本文将介绍如何在手机上使用…

Maven可选依赖和排除依赖简单使用

可选依赖 可选依赖指对外隐藏当前所依赖的资源 在maven_04_dao的pom.xml,在引入maven_03_pojo的时候&#xff0c;添加optional <dependency><groupId>com.rqz</groupId><artifactId>maven_03_pojo</artifactId><version>1.0-SNAPSHOT&…

python-Excel数据模型文档转为MySQL数据库建表语句(需要连接数据库)-工作小记

将指定Excel文档转为create table 建表语句。该脚本适用于单一且简单的建表语句 呈现效果 代码 # -*- coding:utf-8 -*- # Time : 2023/8/2 17:50 # Author: 水兵没月 # File : excel_2_mysql建表语句.py import reimport pandas as pd import mysql.connectordb 库名mydb m…

Excel·VBA表格横向、纵向相互转换

如图&#xff1a;对图中区域 A1:M6 横向表格&#xff0c;转换成区域 A1:C20 纵向表格&#xff0c;即 B:M 列转换成每2列一组按行写入&#xff0c;并删除空行。同理&#xff0c;反向操作就是纵向表格转换成横向表格 目录 横向转纵向实现方法1转换结果 实现方法2转换结果 纵向转横…

Socket层代码重构

src/utils新建socket.js import {io} from "socket.io-client"class Socket{constructor(){this.socket io("http://127.0.0.1:5000");}// 连接socketconnect(){this.socket.connect()}login(username,callback){// emit发送this.socket.emit(login,{&quo…

list交并补差集合

list交并补差集合 工具类依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version> </dependency><dependency><groupId>commons-collections&…

并发编程Part 2

1. JMM 问题&#xff1a;请你谈谈你对volatile的理解? volitile 是 Java 虚拟机提供的一种轻量级的同步机制 &#xff0c;三大特性&#xff1a; 保证可见性 不保证原子性 禁止指令重排 线程之间如何通信&#xff1f; 通信是指线程之间以如何来交换信息。一般线程之间的通信…

HTML+CSS+JavaScript:随机点名案例

一、需求 1、点击开始按钮&#xff0c;姓名随机切换 2、点击结束按钮&#xff0c;姓名停止切换&#xff0c;此时显示的姓名即为被抽中者 3、同一个人不能被重复抽中 二、代码素材 以下是缺失JS部分的代码&#xff0c;感兴趣的小伙伴可以先自己试着写一写 <!DOCTYPE htm…