外观
大模型显存估算与GPU利用率优化
内容整理自学习笔记,仅供面试备考参考;不构成录用、培训或考试承诺。
1. 大模型文件有多大?
一般放出来的模型文件都是 fp16 精度:
| 参数量 | 模型文件大小 | fp16 推理显存 | 对外 PR 参数量 |
|---|---|---|---|
| n B | 2n G | 2n G | 10n 亿 |
例如:7B 模型文件约 14G,推理需要约 14G 显存。
2. 能否用 4 × V100 32G 训练 Vicuna 65B?
不能。原因:
- LLaMA 65B 的权重需要 5 × V100 32G 才能完整加载到 GPU
- Vicuna 使用 Flash-Attention 加速训练,暂不支持 V100,需要 Turing 架构之后的显卡
通过调用 train 脚本(而非 train_mem)训练 Vicuna 是可以尝试的。
3. 显存不多时如何尝试 65B 模型?
最少大概 50G 显存,可以在 llama-65b-int4(GPTQ)模型基础上进行 LoRA 微调,需要安装定制版本的库。
4. nB 模型推理需要多少显存?
考虑模型参数都是 fp16:
推理显存 = 2n G5. nB 模型训练需要多少显存?
5.1 基础显存估算
基础显存 = 模型参数 + 梯度 + 优化器 = 16n G| 组成部分 | 精度 | 大小 | 说明 |
|---|---|---|---|
| 模型参数 | fp16 | 2n G | 前向传播所需 |
| 梯度 | fp16 | 2n G | 反向传播所需 |
| 优化器 | fp32 | 12n G | 必须用 fp32(fp16 会导致训练不稳定),储存一阶+二阶 momentum |
参考 ZeRO 论文:2 + 2 + 12 = 16n G
5.2 实际例子
| 模型 | 计算方式 | 基础显存 | 实际总显存 | 说明 |
|---|---|---|---|---|
| 7B Vicuna | 7 × 16 | 112G | ~160G | FSDP 下勉强可训练 |
全量训练准备显存 20nG 大概是最低要求,除非内存充足可 offload。
5.3 activation 显存
activation 占用显存与 max_len 和 batch_size 有关,需要额外计算。
6. 如何估算模型所需 RAM?
以 LLaMA-7B 为例:
6.1 精度对内存的影响
| 精度 | 每参数所需 bits | 每参数所需 bytes |
|---|---|---|
| fp32 | 32 bits | 4 bytes |
| fp16 | 16 bits | 2 bytes |
| int8 | 8 bits | 1 byte |
6.2 模型 RAM 的三个部分
| 部分 | fp32 计算 | int8 计算 |
|---|---|---|
| 模型参数 | 6B × 4 bytes = 24GB | 6B × 1 byte = 6GB |
| 梯度 | 同参数 = 24GB | 同参数 = 6GB |
| 优化器(AdamW) | 6B × 8 bytes = 48GB | 6B × 2 bytes = 12GB |
AdamW 需要储存两倍模型参数(一阶和二阶 momentum)。
6.3 CUDA Kernel 开销
python
torch.ones((1, 1)).to("cuda")
print_gpu_utilization()
# >>> GPU memory occupied: 1343 MBCUDA kernel 大概占据 1.3GB 左右。
6.4 int8 LLaMA-7B 总内存估算
模型参数(6GB) + 梯度(6GB) + 优化器(12GB) + CUDA(1.3GB) = 25.3GB6.5 中间变量内存
根据 LLaMA 架构计算:
每个 instance = (hidden_size + intermediate_size) × context_length × num_layers × 1byte
= (4096 + 11008) × 2048 × 32 × 1byte
= 990MB| LLaMA 架构参数 | 值 |
|---|---|
| hidden_size | 4096 |
| intermediate_size | 11008 |
| num_hidden_layers | 32 |
| context_length | 2048 |
一张 A100(80GB RAM)大概可以在 int8 精度、
batch_size = 50的设定下进行全参数训练。
7. 如何评估显卡利用率?
7.1 FLOPs 比值法
GPU利用率 = 实测FLOPs / 显卡理论峰值FLOPs| 项目 | 值 |
|---|---|
| 测试工具 | DeepSpeed |
| 参考数据 | NVIDIA 公布的显卡 fp16 峰值计算速度(tensor core) |
| 示例 | 实测 100 TFLOPS / A100 峰值 312 TFLOPS = 32.05% |
7.2 吞吐量估计法
吞吐量 = example数量 / 秒 / GPU × max_length
GPU利用率 = 实际吞吐量 / 论文中的吞吐量(假设利用率100%)| 项目 | 值 |
|---|---|
| 测试工具 | 手动估算或 DeepSpeed |
| 参考数据 | 论文中的训练速度或吞吐量 |
| 示例 | 1536 token/s/gpu / 3300 token/s/gpu(Llama 7B) = 46.54% |
7.3 Torch Profiler 分析法
利用 PyTorch Profiler 记录各函数时间,在 TensorBoard 上展示,在 GPU kernel 视图下查看 tensor core 利用率。
| 项目 | 值 |
|---|---|
| 测试工具 | Torch Profiler + TensorBoard |
| 参考数据 | 无 |
| 示例 | tensor core 利用率 30% |
7.4 三种方法对比
| 对比维度 | 排序 |
|---|---|
| 准确性 | 方案三 > 方案一 > 方案二 |
| 易用性 | 方案二 > 方案一 > 方案三 |
不想改代码用方案二估算;想精确分析训练速度瓶颈用方案三。
8. 显卡利用率测试实现细节
8.1 如何查看多机训练时的网速?
bash
iftop8.2 如何查看多卡之间的 NVLINK topo?
bash
nvidia-smi topo -m8.3 如何查看显卡具体型号?
bash
cd /usr/local/cuda/samples/1_Utilities/deviceQuery
make
./deviceQuery8.4 如何查看训练时的 FLOPs?
基于 DeepSpeed 训练时,通过配置文件启用 FLOPs Profiler:
json
{
"flops_profiler": {
"enabled": true,
"profile_step": 1,
"module_depth": -1,
"top_modules": 1,
"detailed": true,
"output_file": null
}
}8.5 如何查看 DeepSpeed 环境配置是否正确?
bash
ds_report8.6 TF32 格式有多长?
19 位
8.7 哪里查看各类显卡算力比较?
8.8 如何查看训练中的通信开销?
使用 PyTorch Profiler 查看,基于 Transformers 的快捷修改方式可参考:
用记录的 pt.trace.json 文件放到 TensorBoard 上,可看出 tensor core 利用率。
实践经验:使用 DeepSpeed ZeRO-3 时,PCIe 版本的卡大部分时间都在通信上,AllGather 和 ReduceScatter 的时间超过 tensor core 计算的时间,所以 FLOPs 上不去。