torch.multiprocessing

文章目录

  • 张量共享
  • torch.multiprocessing.spawn
  • multiprocessing.Pool与torch.multiprocessing.Pool
    • 阻塞
    • 非阻塞
    • map
      • 阻塞
      • 非阻塞
    • starmap

torch.multiprocessing是具有额外功能的multiprocessing,其 API 与multiprocessing完全兼容,因此我们可以将其用作直接替代品。

multiprocessing支持 3 种进程启动方法:fork(Unix 上默认)、spawn(Windows 和 MacOS 上默认)和forkserver。要在子进程中使用 CUDA,必须使用forkserver或spawn。启动方法应该通过set_start_method()在if name == 'main’主模块的子句中使用来设置一次:

import torch.multiprocessing as mpif __name__ == '__main__':mp.set_start_method('forkserver')...

张量共享

import torch.multiprocessing as mp
import timemat = torch.randn((200, 200))
print(mat.is_shared())queue = mp.Queue()
q.put(a)
print(a.is_shared())
#False
#True
import torch
import torch.multiprocessing as mp
import timedef foo(q):q.put(torch.randn(20, 20))q.put(torch.randn(10, 10))time.sleep(3)def bar(q):t1 = q.get()print(f"Received {t1.size()}")time.sleep(1) # 注意这里不能等待超过3,会导致foo结束,无法获取t2 = q.get()print(f"Received {t2.size()}")if __name__ == "__main__":mp.set_start_method('spawn')queue = mp.Queue()p1 = mp.Process(target=foo, args=(queue,))p2 = mp.Process(target=bar, args=(queue,))p1.start()p2.start()p1.join()p2.join()

仅在Python 3中使用spawn或forkserver启动方法才支持在进程之间共享CUDA张量。

torch.multiprocessing.spawn

torch.multiprocessing.spawn(fn,args=(),nprocs=1,join=True, # join (bool) – 执行一个阻塞的join对于所有进程.daemon=False, # daemon (bool) – 派生进程守护进程标志。如果设置为True,将创建守护进程.start_method="spawn",
)

其中,fn 是要在子进程中运行的函数,args 是传递给该函数的参数,nprocs 是要启动的进程数。当 nprocs 大于 1 时,会创建多个子进程,并在每个子进程中调用 fn 函数,每个子进程都会使用不同的进程 ID 进行标识。当 nprocs 等于 1 时,会在当前进程中直接调用 fn 函数,而不会创建新的子进程。

join=true时,主进程等待所有子进程完成执行并退出,然后继续执行后续的代码。在这个过程中,主进程会被阻塞,也就是说,主进程会暂停执行,直到所有子进程都完成了它们的任务。

torch.multiprocessing.spawn 函数会自动将数据分布到各个进程中,并在所有进程执行完成后进行同步,以确保各个进程之间的数据一致性。同时,该函数还支持多种进程间通信方式,如共享内存(Shared Memory)、管道(Pipe)等,可以根据具体的需求进行选择。

比如下面的fn

def main_worker(gpu, args): # gpu参数控制进程号args.rank = gpu # 用rank记录进程id号dist.init_process_group(backend='nccl', init_method=args.dist_url, world_size=args.num_gpus,rank=args.rank)torch.cuda.set_device(gpu)  # 设置默认GPU  最好方法哦init之后,这样你使用.cuda(),数据就是去指定的gpu上了# 定义模型, 转同步BNmodel = xxxmodel = nn.SyncBatchNorm.convert_sync_batchnorm(model)model.cuda()model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[gpu],find_unused_parameters=True )#定义数据集train_dataset = xxxx# 注意这一步,和单卡的唯一区别。这个sample能保证多个进程不会取重复的数据。shuffle必须设置为False(默认)train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=args.batch_size,num_workers=args.workers, pin_memory=True, sampler=train_sampler)...if args.rank == 0# 主进程torch.save(xx)print(log)

启动代码

import torch.multiprocessing as mp
import torch.distributed as distif __name__ == '__main__':# import configuration file# load json or yaml, argsparseargs = xxxxx# 接下来是设置多进程启动的代码# 1.首先设置端口,采用随机的办法,被占用的概率几乎很低.port_id = 29999args.dist_url = 'tcp://127.0.0.1:' + str(port_id)# 2. 然后统计能使用的GPU,决定我们要开几个进程,也被称为world sizeargs.num_gpus = torch.cuda.device_count()# 3. 多进程的启动torch.multiprocessing.set_start_method('spawn')mp.spawn(main_worker, nprocs=args.num_gpus, args=(args,))

multiprocessing.Pool与torch.multiprocessing.Pool

multiprocessing.Pool创建一个进程池,每个进程都分配一个单独的内存空间。它是一个上下文管理器,因此可以在语句中使用with

with mp.Pool(processes=num_workers) as pool:

等价于

pool = mp.Pool(processes=num_workers)
# do something
pool.close()
pool.join()

阻塞

import time
import multiprocessing as mpdef foo(x, y):time.sleep(3)return x + ywith mp.Pool(processes=4) as pool:a = pool.apply(foo, (1, 2))b = pool.apply(foo, (3, 4))print(a, b)
# 3 7
#---
#Runtime: 6.0 seconds

创建一个包含 4 个工作进程的池,然后向池中提交两个任务来运行。由于apply是阻塞调用,因此主进程将等到第一个任务完成后再提交第二个任务。这基本上是无用的,因为这里没有实现并行性。

with mp.Pool(processes=4) as pool:handle1 = pool.apply_async(foo, (1, 2))handle2 = pool.apply_async(foo, (3, 4))a = handle1.get()b = handle2.get()print(a, b)
# 3 7
#---
#Runtime: 3.0 seconds

非阻塞

apply_async是非阻塞的并AsyncResult立即返回一个对象。然后我们可以使用它get来获取任务的结果。

注意get会阻塞直到任务完成;apply(fn, args, kwargs)相当于apply_async(fn, args, kwargs).get().

还可以加回调函数

def callback(result):print(f"Got result: {result}")with mp.Pool(processes=4) as pool:handle1 = pool.apply_async(foo, (1, 2), callback=callback)handle2 = pool.apply_async(foo, (3, 4), callback=callback)
#Got result: 3
#Got result: 7
#---
#Runtime: 3.0 seconds

map

map将输入的可迭代对象划分为块,并将每个块作为单独的任务提交到池中。然后收集任务的结果并以列表的形式返回。

阻塞

import multiprocessing as mp
import timedef foo(x):print(f"Starting foo({x})")time.sleep(2)return xwith mp.Pool(processes=2) as pool:result = pool.map(foo, range(10), chunksize=None)print(result)
Starting foo(0)
Starting foo(2)
Starting foo(1)
Starting foo(3)
Starting foo(4)
Starting foo(6)
Starting foo(5)
Starting foo(7)
Starting foo(8)
Starting foo(9)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
---
Runtime: 12.0 seconds

在这种情况下,chunksize 自动计算为 2。这意味着可迭代对象被分为 5 个大小为 2: 的块[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]。

map是一个阻塞调用,因此它将等待所有任务完成后再返回。与 apply类似

首先,前两个块[0, 1], [2, 3]分别被提交给2个worker,此时worker0执行0worker1执行2,然后worker0执行1worker1执行3;

然后接下来的两个块[4, 5], [6, 7]被提交。最后,最后一个块[8, 9]被提交给任一worker。

三次提交,每次提交运行2*2秒,共计12s,这不是最优的。在这种情况下,如果我们显式地将 chunksize 设置为 1 或 5,则运行时间将为 10 秒,这已经是最好的了。

非阻塞

with mp.Pool(processes=2) as pool:handle = pool.map_async(foo, range(10), chunksize=None)# do something elseresult = handle.get()print(result)

starmap

map只是将可迭代的元素传递给函数。如果想应用一个多参数函数,我们要么必须传入一个列表并将其解压到函数内。

使用starmap. 对于可迭代的每个元素,starmap将其解压到函数的参数中。

def bar(x, y):print(f"Starting bar({x}, {y})")time.sleep(2)return x + ywith mp.Pool(processes=2) as pool:pool.starmap(bar, [(1, 2), (3, 4), (5, 6)])

starmap是同步的,异步用starmap_async

https://tokudayo.github.io/multiprocessing-in-python-and-torch/#torchmultiprocessing
https://docs.python.org/zh-cn/3.7/library/multiprocessing.html

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

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

相关文章

简单游戏截图_可控截取内容2

一个需求 我需要在场景中截取不同层级的截图(如只截模型或只截UI或只截外部相加看到的画面 或全都截或和Shader配合呈现人眼夜视仪热成像的画面切换) 将截图排到列表中,在场景UI中展示出来 如何做 相机要能够看到不同的画面 将当前帧画面存储下来 将存储的画面展示出…

【数字IC基础】时序违例的修复

时序违例的修复 建立时间违例保持时间违例Buffer 插入位置参考资料 建立时间违例 基本思路是减少数据线的延时、减少 Launch clock line 的延时、增加capture clock line的delay 加强约束,重新进行综合,对违规的路径进行进一步的优化,但是一…

【C++】万能引用、完美转发

万能引用 万能引用的格式如下&#xff1a; template<typename T> void PerfectForward(T&& t) {Fun(t); }虽然写的是&&和右值引用类似&#xff0c;但是它可以接收左值引用和右值引用 当传过来的是左值&#xff0c;那么T&&会折叠为T&。 引用折…

【2023年电赛国一必备】E题报告模板--可直接使用

任务 图1 任务内容 要求 图2 基本要求内容 图3 发挥部分内容 说明 图4 说明内容 评分标准 图5 评分内容 正文 &#xff08;部分&#xff09; 摘要 本文使用K210芯片设计了一个运动目标控制与自动追踪系统。系统包括使用深度学习进行识别激光位置&#xff0c;其中红色激…

Oracle表段中的高水位线HWM

在Oracle数据的存储中&#xff0c;可以把存储空间想象为一个水库&#xff0c;数据想象为水库中的水。水库中的水的位置有一条线叫做水位线&#xff0c;在Oracle中&#xff0c;这条线被称为高水位线&#xff08;High-warter mark, HWM&#xff09;。在数据库表刚建立的时候&…

Emacs之将.el编译成bin(一百二十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Mac 卸载 IntelliJ IDEA 方法

Mac 系统下 IDEA 没有一键卸载程序&#xff0c;也没有完全卸载的插件&#xff0c;若要彻底删除&#xff0c;除了在应用&#xff08;Application&#xff09;里删除 IDEA 到垃圾桶外&#xff0c;还需要在终端&#xff08;Terminal&#xff09;执行删除相应的文件及文件夹。 1 分…

vscode如何退出/切换 github 账号

退出/切换 github 账号 左下角点击头像按钮&#xff0c;选择注销&#xff0c;然后再重新登录

if条件语句

if语句是一种在编程中常用的条件控制语句&#xff0c;用于根据条件来执行不同的代码块。下面是if语句的使用及用法&#xff1a; 基本语法&#xff1a; if 条件: 执行代码块 如果条件为真&#xff0c;则执行代码块&#xff0c;否则跳过。 可选的else语句&#xff1a; if 条件…

JS进阶-Day3

&#x1f954;&#xff1a;永远做自己的聚光灯 JS进阶-Day1——点击此处&#xff08;作用域、函数、解构赋值等&#xff09; JS进阶-Day2——点击此处&#xff08;深入对象之构造函数、实例成员、静态成员等&#xff1b;内置构造函数之引用类型、包装类型等&#xff09; 更多JS…

boost beast http server 测试

boost beast http client boost http server boost beast 是一个非常好用的库&#xff0c;带上boost的协程&#xff0c;好很多东西是比较好用的&#xff0c;以下程序使用四个线程开启协程处理进入http协议处理。协议支持http get 和 http post #include <boost/beast/cor…

Java与Kotline Funcation函数与参数函数的详解

一.介绍 在现在以IDE为开发工具的时代&#xff0c;各种开发语言都有&#xff0c;kotlin的语法势头比较强&#xff0c;今天我们将介绍在项目中出现比较多的两种函数&#xff0c;一种是参数函数&#xff0c;还有一种就是Function函数 如果你不了匿名函数请阅读以下文档&#xff…

ISC 2023︱诚邀您参与赛宁“安全验证评估”论坛

​​8月9日-10日&#xff0c;第十一届互联网安全大会&#xff08;简称ISC 2023&#xff09;将在北京国家会议中心举办。本次大会以“安全即服务&#xff0c;开启人工智能时代数字安全新范式”为主题&#xff0c;打造全球首场AI数字安全峰会&#xff0c;赋予安全即服务新时代内涵…

【华为OD机试】数字最低位排序【2023 B卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 给定一个非空数组(列表) 起元素数据类型为整型 请按照数组元素十进制最低位从小到大进行排序 十进制最低位相同的元素,相对位置保持不变 当数组元素为负值时,十进制最低为等同于去除符号…

常见的设计模式(超详细)

文章目录 单例模式饿汉式单例模式懒汉式单例模式双重检索单例模式 工厂模式简单工厂模式工厂&#xff08;方法&#xff09;模式抽象工厂模式 原型模式代理模式 单例模式 确保一个类只有一个实例&#xff0c;并且自行实例化并向整个系统提供这个实例。 饿汉式单例模式 饿汉式单…

【Vue】全家桶介绍

文章目录 概述核心Vue.Js浏览器开发插件vue-devtools项目构建工具&#xff1a;vue-cli路由管理器 &#xff1a; vue-Router状态管理模式&#xff1a;vuex网络请求库&#xff1a;AxiosUI框架&#xff1a; iview、vant、elementUI打包工具&#xff1a; webpack来源 概述 Vue全家…

编程导航算法村第七关 |二叉树的遍历

编程导航算法村第七关 | 二叉树的遍历 前序遍历&#xff08;递归&#xff09; public List<Integer> preorderTraversal(TreeNode root) {ArrayList<Integer> result new ArrayList<Integer>();preorder(root, result);return result;}public void preorde…

关于win11 debian wsl 子系统安装启动docker一直starting,无法启动

首先我先说明&#xff0c;我的步骤都是按照官网步骤来的 通过官网的操作步骤 通过测试命令 sudo docker run hello-world得到下面的命令&#xff0c;我们通过启动命令 sudo service docker start 执行结果如下图 也就是说无法启动&#xff0c;一直显示在启动中 遇到这种情况…

js实现轮播图(手动+自动)

目录 设置大体样式 图片播放 完整代码 设置大体样式 <input type"button" value"<" id"pre" onclick"pre()" onmouseover"stop()" onmouseout"start()" class"left"> <img src"..…

大数据教材推荐|Python数据挖掘入门、进阶与案例分析

主 编&#xff1a; 卢滔&#xff0c;张良均&#xff0c;戴浩&#xff0c;李曼&#xff0c;陈四德 出版社&#xff1a; 机械工业出版社 内容提要 本书从实践出发&#xff0c;结合11个“泰迪杯”官方推出的赛题&#xff0c;按照赛题的难易程度进行排序&#xff0c;由浅入深…