惠州外贸网站建设推广,手把手做网站,2021企业公司大黄页,个人网页网站制作模板背景
大模型训练好后#xff0c;进行部署时#xff0c;发现可使用的显卡容量远大于模型占用空间 。是否可以同时加载多个模型实例到显存空间#xff0c;且能实现多个实例同时并发执行#xff1f;本次实验测试基于mps的方案#xff0c;当请求依次过来时#xff0c;多个相…背景
大模型训练好后进行部署时发现可使用的显卡容量远大于模型占用空间 。是否可以同时加载多个模型实例到显存空间且能实现多个实例同时并发执行本次实验测试基于mps的方案当请求依次过来时多个相同的实例推理任务就可以同时运行。显然该方法需要显卡测提供某种支持。这种就是 nvidia 的 Multi-Processing Services即显卡多进程服务。一些网上公布的资料[1]主要是基于已经编译好的二进制程序在终端通过指定不同的配置参数如多进程数量测试不同进程数执行同样的推理任务耗时来证明mps对于并发推理任务的支持。本次实验基于Pytorch的模型仓库和多进程库来实现类似的测试。
MPS的开启和关闭
# 服务开启
export CUDA_VISIBLE_DEVICES0
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 copydevice 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 - startprint(forward time cost: %.5f sec %computeTime)return resultreturn wrapperdef getInputData(device device):img Image.open(your/data.jpg).convert(RGB)img torchvision.transforms.ToTensor()(img)print(fimg:{img.shape}, rquires_grad:{img.requires_grad})imgs [img.to(device)]return imgsgetCompDuration
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].shapeprint(fpid:{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 modellistdef 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 50nProcess 2test(nTimes, nProcess)以上代码可分别控制循环执行nTimes次的maskrcnn的前向推理任务和nProcess的进程数观察单进程及多进程执行相同任务的计算耗时。同时可观察打开或者关闭mps服务下单/多进程执行相同任务的耗时表现。这里提供关闭/开启mps服务后一组不同控制变量下的耗时记录。
关闭mps服务下统计不同任务、不同进程数下的耗时情况
nTimes/nProcess1 (单进程)/sec2 (双进程)/sec双进程耗时/单进程耗时505.77(6.80, 5.69)1.0810011.49(19.87, 18.49)1.6720023.40(47.39, 46.01)1.9940045.00(100.18, 98.80)2.21
开启mps服务下统计不同任务、不同进程数下的耗时情况
nTimes/nProcess1 (单进程)/sec2 (双进程)/sec双进程耗时/单进程耗时505.54(5.64, 5.48)1.0010011.08(13.73, 13.36)1.2220023.98(28.45, 27.53)1.1740046.57(59.85, 59.89)1.29400*44.59(killed, 44.210.99
补充实验 400*在双进程运行期间手动关闭一个进程kill -9 进程号。另一个进程会正常运行直至结束其运行时间会接近单进程运行时间。
终端运行结果部分展示
总结
不开启mps服务下相同任务的双进程耗时是单进程耗时的2倍说明双进程是串行运行的。符合预期。开启mps服务下相同让任务的双进程耗时是单进程耗时的1~1.3倍说明两个进程在并发运行但是有抢占某种资源的情况无法做到接近单进程耗时需要进一步研究。
参考文档
[1] 如何使用MPS提升GPU计算收益
[2] IMPROVING GPU UTILIZATION WITH MULTI-PROCESS SERVICE (MPS)