模型训练和推理过程中的显存占用问题

问题背景

我有两个GPT2的模型,模型1只有1亿参数,并以16位浮点数存储,也就是250MB左右,模型2有35亿参数,同样以16位浮点数存储,也就是7GB左右。

我以为推理的时候加载模型到显存中后占用的空间应该也是差不多的大小,但是1亿参数的模型加载到TorchServe中后却占用了957MB,不知道为什么多出来700多MB。

$ nvidia-smi
Sun Mar 19 13:54:05 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.161.03   Driver Version: 470.161.03   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   1  NVIDIA GeForce ...  Off  | 00000000:05:00.0 Off |                  N/A |
| 23%   28C    P8     9W / 250W |    959MiB / 11178MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    1   N/A  N/A   3267643      C   /home/venv/bin/python             957MiB |
+-----------------------------------------------------------------------------+

解释

其实多出来的这部分是CUDA上下文占用的显存开销,它是在执行了第一个CUDA相关操作后创建的。

如果想知道自己显卡的CUDA上下文要占用多少显存,可以创建一个非常简单的张量,然后转移到GPU上,看一下显存占用即可。

$ python
Python 3.9.12 (main, Apr  5 2022, 06:56:58)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> data = [1]
>>> x_data = torch.tensor(data)
>>> x_data.cuda()
tensor([1], device='cuda:0')
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.161.03   Driver Version: 470.161.03   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  Off  | 00000000:04:00.0 Off |                  N/A |
| 23%   33C    P8     9W / 250W |    437MiB / 11178MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
|   1  NVIDIA GeForce ...  Off  | 00000000:05:00.0 Off |                  N/A |
| 23%   28C    P8     9W / 250W |    959MiB / 11178MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A   3307828      C   python                            435MiB |
|    1   N/A  N/A   3267643      C   /home/venv/bin/python             957MiB |
+-----------------------------------------------------------------------------+

可以发现,即使我们创建了一个只包含一个元素的张量,但是显存的占用还是达到了435MB。

CUDA上下文占用的显存跟模型大小并不相关,只跟显卡型号有关。也就是说,相比于小模型,大模型占用的CUDA上下文并不会突出多少。

实验代码

实验模型

# 保存1亿参数的模型
from transformers import GPT2Tokenizer, GPT2LMHeadModel
hf_model_path = "IDEA-CCNL/Wenzhong-GPT2-110M"
tokenizer = GPT2Tokenizer.from_pretrained(hf_model_path)
model = GPT2LMHeadModel.from_pretrained(hf_model_path)
model.half()
model.save_pretrained("Wenzhong-GPT2-110M")

TorchServe

模型处理脚本:Transformer_handler_generalized.py

import torch as th
from transformers import GPT2LMHeadModel, GPT2TokenizerFast
from ts.torch_handler.base_handler import BaseHandler


class TransformersGpt2Handler(BaseHandler):
	def __init__(self):
		super(TransformersGpt2Handler, self).__init__()
		self.initialized = False

	def initialize(self, ctx):
		self.manifest = ctx.manifest
		properties = ctx.system_properties
		model_dir = properties.get("model_dir")

		self.device = th.device(
			"cuda:" + str(properties.get("gpu_id"))
			if th.cuda.is_available() and properties.get("gpu_id") is not None
			else "cpu"
		)

		self.model = GPT2LMHeadModel.from_pretrained(model_dir, torch_dtype=th.float16)
		self.model.to(self.device)

		hf_model_path = "IDEA-CCNL/Wenzhong-GPT2-110M"
		self.tokenizer = GPT2TokenizerFast.from_pretrained(hf_model_path)
		self.end_token_id = self.tokenizer.add_special_tokens({"pad_token": "<|endoftext|>"})

		self.model.eval()
		self.initialized = True

	def preprocess(self, requests):
		inputs = None
		for idx, data in enumerate(requests):
			input_text = data.get("body").get("prompt")
			if isinstance(input_text, (bytes, bytearray)):
				input_text = input_text.decode("utf-8")
			inputs = self.tokenizer(input_text, return_tensors="pt")
		return inputs

	def inference(self, data, *args, **kwargs):
		generation_output = self.model.generate(
			**data.to(self.device), return_dict_in_generate=True, top_k=4, penalty_alpha=0.6,
			output_scores=True, do_sample=True, eos_token_id=91)
		return generation_output

	def postprocess(self, inference_output):
		inferences = []
		for idx, sentence in enumerate(inference_output.sequences):
			output = self.tokenizer.decode(sentence)
			inferences.append(output)
		return [inferences]

模型打包

torch-model-archiver --model-name Wenzhong-GPT2-110M --force --version 1.0 --serialized-file Wenzhong-GPT2-110M/pytorch_model.bin  --handler Transformer_handler_generalized.py    --export-path model_store/ --extra-files "Wenzhong-GPT2-110M/config.json"

拉取并启动TorchServe镜像

docker pull pytorch/torchserve:latest-gpu

config.properties配置文件

inference_address=http://0.0.0.0:8080
management_address=http://0.0.0.0:8081
metrics_address=http://0.0.0.0:8082

number_of_netty_threads=32
job_queue_size=1000
model_store=/home/model-server/model-store
workflow_store=/home/model-server/wf-store

cors_allowed_origin=*
cors_allowed_methods=*

install_py_dep_per_model=true

default_response_timeout=600

启动TorchServe

docker run --rm -it -d --name Wenzhong --gpus all -p 18080:8080 -p 18081:8081 -v ${pwd}/model_store:/home/model-server/model-store pytorch/torchserve:latest-gpu

安装transformers

docker exec Wenzhong pip install -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com transformers

注册模型

curl -X POST "http://localhost:18081/models?url=Wenzhong-GPT2-110M.mar"
curl -X PUT  "http://localhost:18081/models/Wenzhong-GPT2-110M?min_worker=1"
curl -X POST 'http://localhost:18080/predictions/Wenzhong-GPT2-110M' --data '{"prompt": "你是谁?"}'

参考资料

GitHub Issue: The memory occupied by the model becomes larger after it is loaded into the GPU

<think>嗯,用户现在问的是AI模型训练推理的区别。之前他们问过DeepSeek各个模型之间的区别以及手机App用的是哪个模型,现在这个问题看起来是更基础的概念性问题。可能需要先确认用户的需求是什么,他们可能是在学习AI基础知识,或者想了解技术细节以便更好地使用相关应用。 首先,用户可能已经了解了一些模型的应用,比如手机App使用的模型,现在想深入理解背后的技术流程。训练推理是机器学习中的两个核心阶段,需要明确区分它们的定义、目的、资源消耗、执行过程应用场景。 我需要先回忆训练推理的基本区别。训练是指用大量数据让模型学习参数,调整权重以最小化损失函数的过程。而推理则是使用训练好的模型对新数据进行预测或生成结果。接下来要考虑用户可能的实际应用场景,比如他们可能在开发或优化自己的模型,或者只是好奇技术细节。 用户可能没有明确说出来的需求是,他们可能想优化应用的性能,比如减少延迟或计算资源消耗,所以了解训练推理的区别有助于他们理解为什么推理可以在手机端运行,而训练需要更的资源。比如之前的回答提到手机App使用轻量化的1.3B模型进行本地推理,而训练可能需要更大的模型GPU集群。 还需要注意用户可能对术语不太熟悉,需要用通俗易懂的语言解释,避免过技术术语,同时保持准确性。例如,用“学习”来比喻训练,用“应用”来比喻推理,可能更容易理解。 另外,可能需要举例说明,比如训练像学生学习知识,推理像考试答题。这样用户更容易联想。同时,要强调资源消耗的不同,比如训练需要大量计算力时间,而推理需要快速响应,适合在手机等设备上运行。 还要考虑用户是否有兴趣了解如何优化推理效率,比如模型压缩、量化等技术,这些在之前的回答中提到的手机端使用INT8量化模型,可以联系起来。这样让用户看到知识点的连贯性。 总结来说,回答需要结构清晰,分点列出训练推理的区别,每个点用简明的语言解释,辅以例子实际应用场景,帮助用户建立全面的理解。同时,结合之前的回答,展示相关知识点的联系,增强用户的整体认知。</think>以下是关于AI模型训练推理的区别的清晰对比分析: --- ### **核心区别概览** | **维度** | **训练(Training)** | **推理(Inference)** | |---------|-----------------------------------| | **目的** | **让模型学习规律**(参数优化) | **用模型解决问题**(应用已学知识) | | **资源消耗** | 极高(算力/时间/数据) | 较低(可轻量化部署) | | **执行频率** | 一次性或周期性(模型更新时) | 高频实时(用户触发即用) | | **硬件依赖** | 需GPU/TPU集群(如NVIDIA A100) | 可适配手机/边缘设备(如高通骁龙) | --- ### **一、流程与目标差异** 1. **训练阶段** - **核心任务**:通过海量数据输入,**反向传播**调整模型权重,使输出逼近真实值 - **关键指标**:损失函数(Loss)下降、准确率提升 - **典型耗时**:GPT-3训练需数千张GPU运行数周 2. **推理阶段** - **核心任务**:加载训练好的模型权重,**前向传播**计算输入数据的预测结果 - **关键指标**:响应延迟(如手机端要求<1秒)、内占用 - **典型场景**:ChatGPT生成回复、手机拍照识图 --- ### **二、技术实现对比** | **技术环节** | 训练 | 推理 | |--|-----------------------------|-----------------------------| | **计算模式** | 反向传播+梯度下降 | 仅前向传播 | | **精度要求** | FP32(避免精度丢失) | INT8量化常见(牺牲少量精度换速度) | | **并行化** | 数据并行/模型并行(GPU协同) | 单设备为主(部分云端支持批处理) | | **内占用** | 显存需求与模型参数正相关(如175B GPT-3需TB级显存) | 通过模型压缩可降至百MB级(如MobileBERT仅17MB) | --- ### **三、实际案例说明** - **图像分类模型训练**: 使用ImageNet数据集(1400万图片),在8张A100上训练ResNet-50需56小时,调整数百万参数 - **同模型推理**: 部署到手机后,单张照片分类仅需50ms,消耗CPU算力不足1% --- ### **四、优化方向差异** 1. **训练优化重点** - 提升分布式计算效率(如Megatron-LM框架) - 改进收敛速度(自适应学习率算法) - 数据增强与清洗 2. **推理优化重点** - 模型压缩(剪枝/量化/知识蒸馏) - 硬件加速(NPU指令集优化) - 请求批处理(Cloud GPU合并计算) --- ### **五、关联性与协同** - **迭代闭环**:推理阶段收集的用户反馈数据(如错误标注)可反哺训练数据优化 - **边缘计算趋势**:部分设备支持**联邦学习**(本地训练+全局模型更新) --- ### **通俗类比** - **训练** ≈ **学生上课学习**:需要大量书本(数据)、长时间专注(算力)、老师指导(损失函数) - **推理** ≈ **学生参加考试**:快速调用已学知识解决问题,追求效率与准确性 如需进一步了解特定场景(如手机端推理加速技术),可提供具体案例展开说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Matrix 工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值