基于mps的pytorch 多实例并行推理

news2024/11/21 0:25:14
背景

大模型训练好后,进行部署时,发现可使用的显卡容量远大于模型占用空间 。是否可以同时加载多个模型实例到显存空间,且能实现多个实例同时并发执行?本次实验测试基于mps的方案,当请求依次过来时,多个相同的实例推理任务就可以同时运行。显然,该方法需要显卡测提供某种支持。这种就是 nvidia 的 Multi-Processing Services,即显卡多进程服务。一些网上公布的资料[1],主要是基于已经编译好的二进制程序在终端,通过指定不同的配置参数,如多进程数量,测试不同进程数执行同样的推理任务耗时,来证明mps对于并发推理任务的支持。本次实验基于Pytorch的模型仓库和多进程库,来实现类似的测试。

MPS的开启和关闭
# 服务开启
export CUDA_VISIBLE_DEVICES=0
nvidia-smi -i 0 -c 3 # -c 3 同 -c EXCLUSIVE_PROCESS
nvidia-cuda-mps-contrl -d

服务开启成功后并不会有任何显示,只有当运行一次任务后才能看到服务进程。
在这里插入图片描述

# 服务关闭
sudo nvidia-cuda-mps-control quit # 通常不能关闭mps服务,需要强制关闭
ps -ef | grep mps  # 查看mps的进程号
sudo kill -9 mps的进程号
Pytorch 多进程管理多个cuda流

nvidia显卡上的并发推理计算,是通过cuda流来管理的。在 mps 服务的模型中,cpu进程与cuda流的关系,可以总结为,一个cpu进程管理一个或多个流 [2]
在这里插入图片描述

一个流对应一个工作队列

一个流对应一个工作队列

客户端一个进程管理两个流

根据以上文献资料指导,编写基于Pytorch多进程客户端测试代码:

import torch
import torchvision
import time
import os
import torchvision.models as models
from PIL import Image
import copy

device = torch.device('cuda')

# 装饰器,用于计算推理耗时
def getCompDuration(func):
    def warpper(*args, **kwargs):
        print("%s is running" % func.__name__)
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        computeTime = end - start
        print('forward time cost: %.5f sec' %computeTime)
        return result
    return wrapper

def getInputData(device = device):
    img = Image.open('your/data.jpg').convert('RGB')
    img = torchvision.transforms.ToTensor()(img)
    print(f'img:{img.shape}, rquires_grad:{img.requires_grad}')
    imgs = [img.to(device)]
    return imgs

@getCompDuration
def modelForwardImage(input, model, nTimes, stream, device = device):
    pid = os.getpid()
    model.eval()
    
    for i in range(nTimes):
        with torch.no_grad(): # 非常重要,用于降低显存消耗
            predictions = model(input)
            pred = predictions[0]['boxes'].shape
            print(f'pid:{pid}, stream:{stream}, predict result:{pred}')

def getModels(nProcess, device = device):
    modellist = []
	with torch.no_grad():
		model = models.detection.maskrcnn_resnet50_fpn(pretrained = False, pretrained_backbone = False)
        model.load_state_dict(torch.load('./your/dir/maskrcnn_resnet50_fpn_coco-bf2d0c1e.pth'))
        for i in range(nProcess):
            mod = copy.deepcopy(model)
            mod.to(device)
            modellist.append(mod)
        return modellist
    
def funcInStream(input, model, nTimes):
    stream = torch.cuda.Stream()
    with torch.cuda.stream(stream):
        modelForwardImage(input, model, nTimes, stream)
        
def test(nTimes, nProcess):
    input = getInputData()
    
    # spwan是多任务的一种方式
    ctx = torch.multiprocessing.get_context('spawn')
   
    models = getModels(nProcess)
    pool = []
    for i in range(nProcess):
        p = ctx.Process(target = funcInStream, args = (input, models[i], nTimes))
        pool.append(p)
    
    for p in pool:
        p.start()

if __name__ == '__main__':
    nTimes = 50
    nProcess = 2
    test(nTimes, nProcess)

以上代码,可分别控制循环执行nTimes次的maskrcnn的前向推理任务,和nProcess的进程数,观察单进程及多进程执行相同任务的计算耗时。同时可观察打开或者关闭mps服务下,单/多进程执行相同任务的耗时表现。这里提供关闭/开启mps服务后,一组不同控制变量下的耗时记录。

关闭mps服务下,统计不同任务、不同进程数下的耗时情况

nTimes/nProcess1 (单进程)/sec2 (双进程)/sec双进程耗时/单进程耗时
505.77(6.80, 5.69)1.08
10011.49(19.87, 18.49)1.67
20023.40(47.39, 46.01)1.99
40045.00(100.18, 98.80)2.21

开启mps服务下,统计不同任务、不同进程数下的耗时情况

nTimes/nProcess1 (单进程)/sec2 (双进程)/sec双进程耗时/单进程耗时
505.54(5.64, 5.48)1.00
10011.08(13.73, 13.36)1.22
20023.98(28.45, 27.53)1.17
40046.57(59.85, 59.89)1.29
400*44.59(killed, 44.21)0.99

补充实验 400*,在双进程运行期间,手动关闭一个进程,kill -9 进程号。另一个进程会正常运行直至结束,其运行时间会接近单进程运行时间。

终端运行结果部分展示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结
  1. 不开启mps服务下,相同任务的双进程耗时是单进程耗时的2倍,说明双进程是串行运行的。符合预期。
  2. 开启mps服务下,相同让任务的双进程耗时是单进程耗时的1~1.3倍,说明两个进程在并发运行,但是有抢占某种资源的情况,无法做到接近单进程耗时,需要进一步研究。
参考文档

[1] 如何使用MPS提升GPU计算收益

[2] IMPROVING GPU UTILIZATION WITH MULTI-PROCESS SERVICE (MPS)

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

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

相关文章

NDK打印android日志

首先在cpp文件中 引入 #include <android/log.h> 然后就可以使用 __android_log_print方法&#xff0c;第一个参数是log level&#xff0c;第二个是tag&#xff0c;第三个是日志内容。 #include <jni.h> #include <string> #include <android/log.h&g…

2023-12-01 事业-代号s-如何装修“高转化“首页

摘要: 2023-12-01 事业-代号s-如何装修"高转化"首页 如何装修"高转化"首页 影响独立站转化率6大因素:产品、素材、受众、落地页、结算流程、复购。 今天就来分享下,独立站高转化首页如何装修?整个网站首页框架应该放置什么内容? 传统设计 VS 8P设计 …

模糊C均值(Fuzzy C-means,FCM)聚类的python程序代码的逐行解释,看完你也会写!!

文章目录 前言一、本文的原始代码二、代码的逐行详细解释总结 前言 接上一篇博客&#xff0c;详细解释FCM聚类的程序代码&#xff01;&#xff01; 一、本文的原始代码 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets import skfuzzy as…

【开源】基于JAVA的厦门旅游电子商务预订系统

项目编号&#xff1a; S 030 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S030&#xff0c;文末获取源码。} 项目编号&#xff1a;S030&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 景点类型模块2.2 景点档案模块2.3 酒…

多线程(初阶五:wait和notify)

目录 一、概念 二、用法 &#xff08;1&#xff09;举个栗子&#xff1a; &#xff08;2&#xff09;wait和notify的使用 1、没有上锁的wait 2、当一个线程被wait&#xff0c;但没有其他线程notify来释放这个wait 3、两个线程&#xff0c;有一个线程wait&#xff0c;有一…

React项目使用NProgress作为加载进度条

React项目使用NProgress作为加载进度条 0、效果1、react安装依赖2、使用3.进度条颜色设置 文档参考&#xff1a;https://zhuanlan.zhihu.com/p/616245086?utm_id0 0、效果 如下&#xff0c;可全局在页面顶部有一条进度条 1、react安装依赖 yarn add nprogress通过以上安装…

vue之mixin混入

vue之mixin混入 mixin是什么&#xff1f; 官方的解释&#xff1a; 混入 (mixin) 提供了一种非常灵活的方式&#xff0c;来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时&#xff0c;所有混入对象的选项将被“混合”进入该组件本身的…

二次元检测设备导轨修复指南

二次元检测设备是一种高精度的测量仪器&#xff0c;用于检测物体表面的形状、尺寸和精度等。直线导轨是二次元检测设备中最重要的组成部分之一&#xff0c;它的精度和稳定性直接影响到设备的测量结果和可靠性&#xff0c;因此&#xff0c;对导轨进行修复和保养是非常重要的。 直…

网络类型解析(基础):探索通信世界的多样面貌

在当今数字化时代&#xff0c;网络已经成为人们生活和工作中不可或缺的一部分。从个人设备之间的直接通信到全球范围的数据传输&#xff0c;不同类型的网络为我们提供了多种连接方式和通信选择。透过对这些网络类型的解析&#xff0c;我们将更好地理解它们的特点、优势和适用场…

九章量子计算机:探索量子世界的革命性工具

九章量子计算机:探索量子世界的革命性工具 一、引言 九章量子计算机的推出,是近年来科技界最为引人瞩目的成就之一。这款基于量子力学的计算机,以其独特的计算方式和潜在的应用前景,引发了全球范围内的关注和讨论。本文将深入探讨九章量子计算机的原理、技术特点、应用前景…

nodejs_vue+vscode美容理发店会员管理系统un1dm

按照设计开发一个系统的常用流程来描述系统&#xff0c;可以把系统分成分析阶段&#xff0c;设计阶段&#xff0c;实现阶段&#xff0c;测试阶段。所以在编写系统的说明文档时&#xff0c;根据系统所处的阶段来描述系统的内容。 绪论&#xff1a;这是对选题的背景&#xff0c;意…

PHP实践:用ThinkPHP6完整实现用户分页功能

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

WPF Mvvm模式下面如何将事件映射到ViewModel层

前言 平常用惯了Command绑定,都快忘记传统的基于事件编程模式了,但是Commond模式里面有个明显的问题,就是你无法获取到事件源的参数。很多大聪明肯定会说,这还不简单,通过自己写控件,给控件加个自定义属性不就行了,想要啥事件就写啥事件进去,完全自主可控。但是对于写…

Day04:每日一题:2661. 找出叠涂元素

2661. 找出叠涂元素 给你一个下标从 0 开始的整数数组 arr 和一个 m x n 的整数 矩阵 mat 。 arr 和 mat 都包含范围 [1&#xff0c;m * n] 内的 所有 整数。从下标 0 开始遍历 arr 中的每个下标 i &#xff0c;并将包含整数 arr[i] 的 mat 单元格涂色。请你找出 arr 中在 mat…

【数电笔记】逻辑代数的基本定律、常用公式

说明&#xff1a; 笔记配套视频来源&#xff1a;B站 逻辑代数的基本定律 1. 常量间的运算 2. 逻辑变量与常量的运算 3. 与普通代数相似的定律 4. 摩根定律&#xff08;反演律&#xff09; 5. 等式证明方法例题 逻辑代数的常用公式 1. 吸收律 2. 冗余律 3. 示例应用 4. 关于异…

stm32的中断复习

(https://img-blog.csdnimg.cn/4fa918bc1ebb41118410bc9a41d4b296.jpg)

lxml 总结

xm 和 lxml库 哪个更好用点 1. 性能&#xff1a; lxml 通常比 xml.etree.ElementTree 更快。lxml 使用了 C 编写的底层解析器&#xff0c;因此在处理大型 XML 文档时可能更高效。 如果性能对你的应用很重要&#xff0c;特别是在处理大型 XML 文件时&#xff0c;选择 lxml 可能…

shell编程系列(9)-使用cut选择列

文章目录 前言使用cut选择列选择特定的列 结语 前言 前面的文章介绍了sed命令&#xff0c;sed可以帮我们处理文本列&#xff0c;这边文章介绍cut命令&#xff0c;cut命令可以帮我们选择想要的列&#xff0c;在文本处理时候结合sed命令&#xff0c;就可以精准定位了。 cut命令是…

前端面试高频考点—TCP vs UDP

目录 简介&#xff1a; 区别&#xff1a; 应用选择&#xff1a; tcp为什么需要三次握手&#xff1f; 简介&#xff1a; TCP(传输控制协议)和UDP&#xff08;用户数据报协议&#xff09; TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议&#xff0c;是专门为了在不…

代码随想录算法训练营第三十六天| 435 无重叠区间 763 划分字母区间 56 合并区间

目录 435 无重叠区间 763 划分字母区间 56 合并区间 435 无重叠区间 将intervals数组按照左端点进行升序排序。 设置变量len标志此时新加入端点后所有区间的位置&#xff0c;将其赋初值为第一对区间的右端点&#xff0c;因为该点是一定可达的。设置变量res来存储需要移除空间…