工程

如何微调 70B 模型:GPU 要求与工作流程

对 70B 模型而言,全参数微调、LoRA 和 QLoRA 所需的硬件差别很大。本文给出每种方法背后的显存计算、装得下的 GPU,以及一套经得起实践检验的工作流程。

阅读约 9 分钟

微调 70B 模型,既可以只用单张 GPU,也可以动用一整台 8 卡服务器,两个答案都没错:关键在于您是更新全部权重,还是在 16 位权重上训练 LoRA 适配器,抑或是用 QLoRA 在 4 位基座模型上训练适配器。所需显存从约 40 GB 到远超 1 TB 不等。本指南将说明这些数字从何而来、每种方法需要哪些 GPU,以及如何完成从数据准备到推理部署的全过程。文中的示例采用 Llama 3.1 70B:80 层,隐藏层维度为 8,192,有 8 个 KV 头。

70B 模型微调的 GPU 要求一览

方法显存中存放的内容总量(不计激活值)最低配置宽裕配置
全参数微调(AdamW,混合精度)权重、梯度、FP32 主权重和两个 Adam 矩:每个参数 16–20 字节1.12–1.4 TB8× H200(需将优化器状态卸载到 CPU 内存),或采用精简 16 字节方案的 8× B2008× B300
BF16 基座模型上的 LoRA冻结的 16 位权重,加上适配器及其优化器状态约 145 GB2× 80 GB(仅限短序列),或单张 B2008× H100 或 8× H200,或单张 B300
4 位基座模型上的 QLoRA冻结的 4 位权重,加上适配器约 40–45 GB单张 80 GB H100单张 H200,可处理更长的序列

做预算时可以参考这些配置的月价:单张 H100 为 US$2,190,单张 H200 为 US$3,090,单张 B200 为 US$4,590,单张 B300 为 US$5,190,8× H100 为 US$16,900,8× H200 为 US$23,900,8× B200 为 US$34,900,8× B300 为 US$39,900。一个月的租期也足以跑上好几轮训练,而微调通常正是这样反复进行的。本指南的其余部分会解释这些数字;其背后的通用估算方法,请参阅我们的大语言模型(LLM)显存需求指南。

全参数微调:为什么需要 1 TB 以上

使用 AdamW 的标准混合精度训练,要为每个参数保存五个数值:

状态精度每个参数的字节数70B 模型
权重BF162140 GB
梯度BF162140 GB
权重的主副本FP324280 GB
Adam 一阶矩FP324280 GB
Adam 二阶矩FP324280 GB
合计161,120 GB

如果方案以 FP32 保存梯度或通信缓冲区,每个参数就接近 20 字节,即 1.4 TB。无论哪种情况,还没存下任何一个激活值,训练状态就已超过 1 TB。

没有哪张 GPU 能单独装下这么多数据,普通的数据并行也无济于事,因为每张 GPU 都要保存一份完整副本。您需要分片:PyTorch FSDP 或 DeepSpeed ZeRO 第 3 阶段会把权重、梯度和优化器状态切分到所有 GPU 上,只在某一层进行计算时才汇集该层的权重。分布到 8 张 GPU 上,按每个参数 16 字节计算,每张 GPU 要存放 140 GB 状态;按 20 字节计算则为 175 GB。这笔账决定了硬件的选择:

  • 8× H100(共 640 GB)在单台服务器上装不下训练状态。
  • 8× H200(每张 141 GB)能在每张 GPU 上放下 140 GB 状态,但不会给激活值留下任何空间。只有把 FP32 主权重和 Adam 矩移到 CPU 内存中(约 840 GB,服务器的 2 TB 内存装得下),或者在分片方案支持的前提下改用 8 位优化器状态来压缩它们,才能跑得起来。卸载会拖慢每一步,因为优化器在 CPU 上运行,状态数据还要经过 PCIe 传输。
  • 8× B200(每张 180 GB)按每个参数 16 字节计算,每张 GPU 还剩约 40 GB 可用于激活值和缓冲区,配合激活检查点即可运行。若方案更接近每个参数 20 字节,则几乎没有剩余空间,同样需要卸载。
  • 8× B300(每张 288 GB)在每张 GPU 上剩余的空间远超 100 GB,无需任何技巧,就能支持更长的序列和更大的微批次。

用高速网络连接两台服务器也是一条路,但对 70B 模型做全参数微调,很少是应当首先尝试的方案。对于大多数指令微调和领域适配任务,请从 LoRA 入手;只有在您拥有足够的数据,并有证据表明适配器是瓶颈时,才转向全参数微调。真正需要时,我们的 8 卡服务器是裸金属服务器,8 张 GPU 之间全部通过 NVLink 互联。

激活值显存与序列长度

激活值是这笔账的另一半,而且是随数据增长的那一半。在前向传播过程中,每一层都要保留中间张量,供反向传播使用。对于 BF16 精度、Llama 架构的 70B 模型,80 层合计每个 token 约需 25 MB,因此单个 8,192 token 的序列就要在其所在的 GPU 上占用约 200 GB。分片并不能减少这部分占用,因为每张 GPU 都要存放自己那个微批次的激活值。

激活检查点(也称梯度检查点)可以解决这个问题。每一层不再保留全部中间结果,而只存储自己的输入,即每个 token 一个由 8,192 个 BF16 值组成的向量(16 KB),其余部分则在反向传播时重新计算。这样一来,80 层合计每个 token 约 1.3 MB,单个 8,192 token 的序列约 11 GB,另需几 GB 工作空间,供正在重新计算的那一层使用。代价是每一步大约多出一次前向传播的计算量。

还有两点常常让人措手不及。Llama 3.1 的词表有 128,256 个 token,单个 8,192 token 序列在整个词表上的输出 logits 以 FP32 存储约需 4.2 GB,这还不算它们的梯度;采用融合或分块实现的损失函数,可以避免一次性把它们全部生成出来。此外,序列长度是您手中最主要的调节杠杆:把短样本打包在一起,把微批次控制在一到两个序列,再用梯度累积达到您想要的有效批大小。

BF16 精度的 LoRA:冻结权重决定了显存下限

LoRA 会冻结基座模型,只在选定的投影层旁边训练小型低秩矩阵。但基座权重仍须驻留在显存中:BF16 精度下约 140 GB。相比之下,适配器非常小。如果在 80 层中每一层的全部 7 个投影矩阵上应用秩为 16 的 LoRA,会增加约 2.07 亿个可训练参数,约占模型的 0.3%;连同它们的梯度和优化器状态,约为 3.3 GB。

激活值并不会减少多少,因为梯度仍要反向流经冻结的各层,才能到达靠前各层中的适配器,所以请保持激活检查点开启。处理单个 8,192 token 的序列,总共约需 160 GB。硬件选择由此而定:

  • 2× 80 GB 是下限:共 160 GB,只够处理短序列。
  • 8× H100 或 8× H200 则很宽裕。冻结权重分片到 8 张 GPU 上后,每张 GPU 只占 17.5 GB,既能为长序列留出空间,也能在全部 8 张 GPU 上做数据并行。
  • 单张 GPU 同样可行,无需配置分片,但速度也只有一张 GPU 的水平:在 8,192 token 下,180 GB 的 B200 能装下这个任务,还剩约 20 GB;288 GB 的 NVIDIA B300 则绰绰有余。

使用 Hugging Face PEFT 时,针对 Llama 架构模型的典型配置会覆盖所有线性投影层:

from peft import LoraConfig

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    task_type="CAUSAL_LM",
)

QLoRA 的作者在实验中发现,要达到全参数微调的效果,必须把适配器应用到所有线性层,而不只是注意力层。对大模型做 LoRA 时,1e-4 左右的学习率是常见的起点,约为全参数微调所用学习率的十倍。

QLoRA:在单张 GPU 上微调 70B 模型

QLoRA 以 4 位 NF4 格式存储冻结的基座模型,在其之上训练 16 位 LoRA 适配器,并在计算时实时反量化权重。这样,70B 基座模型约占 35 GB;加上量化常数,以及保持 16 位的嵌入层和输出层,实际约为 40 GB。再加上适配器及其优化器状态所需的 3–4 GB,以及单个 8,192 token 序列在启用激活检查点后约 14 GB 的激活值,整个任务就能装进一张 80 GB 的 NVIDIA H100。141 GB 的 H200 则能为更长的序列或更大的微批次留出空间。

最初的 QLoRA 论文在单张 48 GB GPU 上微调了一个 65B 模型。Llama 3.1 70B 的规模略大,词表也是前者的四倍,因此请按 80 GB 来规划。使用 Transformers 和 bitsandbytes 以 4 位精度加载基座模型的代码如下:

import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=True,
    bnb_4bit_compute_dtype=torch.bfloat16,
)
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-70B-Instruct",
    quantization_config=bnb_config,
    device_map="auto",
)

代价在于:由于需要反量化,每一步都比 BF16 LoRA 慢;而且适配器是在量化模型上学习的,这个模型与您最终很可能用于部署的 BF16 模型略有不同。请在合并之后进行评测,而不要只在训练过程中评测。

如何微调 70B 模型:一套实用的工作流程

硬件是最容易的部分。大多数失败的微调,栽在数据或评测上,而不是显存上。

  1. 准备数据。把样本整理成对话格式,并用模型自带的对话模板渲染(在 Transformers 中使用 tokenizer.apply_chat_template)。去重,过滤掉低质量样本,并删除不应用于训练的个人数据。留出一份评测集,且绝不用它训练。统计 token 长度:您保留的最长序列决定了激活值所需的显存。
  2. 选择工具。Hugging Face TRL 配合 PEFT,提供用于监督微调和偏好微调的训练器,并可借助 Accelerate、FSDP 或 DeepSpeed 进行多 GPU 训练。Axolotl 用 YAML 配置文件封装了同样的基础组件。torchtune 提供 PyTorch 原生的训练配方,涵盖全参数微调、LoRA 和 QLoRA。三者都支持上述方法;选择配置风格最便于您的团队长期维护的那一个即可。
  3. 固定环境。使用容器或虚拟环境,并固定 PyTorch、Transformers、PEFT 和训练框架的版本,确保下个月重新运行时表现一致。
  4. 先在小模型上做冒烟测试。用同一套流水线在 8B 模型上跑几百步。这样能在模板、掩码和数据方面的错误让您白白浪费一次长时间训练之前,就把它们揪出来。
  5. 启动并监控。用 torchrun --nproc_per_node=8 train.py 或所用工具自带的启动器启动多 GPU 任务,并放在 tmux 中运行,这样即使 SSH 连接断开,训练也不会中断。密切关注训练损失和评测损失、显存占用以及每步耗时;一旦出现损失骤升或评测损失上升,就应当提前停止。

关于 8 卡服务器上的通信问题,请参阅我们的多 GPU 与 NCCL 指南。

把检查点存放在 NVMe 上

检查点体积很大,最好存放在高速本地磁盘上:

  • 全参数微调:包含优化器状态、可用于恢复训练的检查点,大小与训练状态相当,为 1.1–1.4 TB。请以分片方式写入,让每个 rank 并行保存自己的那一部分。
  • 仅模型权重:BF16 精度下约 140 GB,用于评测和推理部署。
  • LoRA 适配器:秩为 16、BF16 精度时约 0.4 GB,因此可以保留很多个。

我们的 HGX 服务器配备 8× 3.84 TB NVMe 存储,足以存放数据集、基座模型和多个完整检查点。单卡 H100 套餐配备 2 TB,用于 QLoRA 绰绰有余,此时最大的文件就是下载的 BF16 基座模型。请在本地保留最近几个检查点,把效果最好的那个复制到服务器之外;同时请记住,除非另有书面约定,我们不会备份本地磁盘。详情请参阅本地 NVMe 存储指南。

先评测,再部署

请使用相同的提示词、对话模板和采样设置,与基座模型进行对比评测:

  • 留出评测集上的损失,用于发现过拟合。
  • 您自己评测集上的任务指标:精确匹配、评分细则或成对偏好比较。
  • 一组通用提示词构成的回归测试集,用于发现模型丢失的能力,例如指令遵循或用其他语言作答。
  • 人工阅读一部分输出样本。自动评判有帮助,但难免有遗漏。

部署推理服务有两种方式。一是用 PEFT 中的 merge_and_unload() 把适配器合并到基座权重中,然后部署合并后的模型;如果想在单张 H200 上运行,可将其量化为 FP8。合并需要 BF16 精度的基座模型,约 140 GB,我们单卡 H100 套餐的 225 GB 内存装得下。二是让基座模型保持加载状态,在运行时挂载适配器:vLLM 可以基于同一个基座模型,同时为多个 LoRA 适配器提供推理服务。服务端的搭建,请参阅我们关于使用 vLLM 自托管 LLM 推理的指南。如果您正在规划训练任务,请查看我们用于微调的 GPU 服务器。

常见问题

微调 70B 模型需要多少显存?

不计激活值,QLoRA 约需 40–45 GB,基于 BF16 基座模型的 LoRA 约需 145 GB。使用 AdamW 做全参数微调,仅权重、梯度和优化器状态就需要 1.12–1.4 TB。

能在单张 GPU 上微调 70B 模型吗?

可以,用 QLoRA 即可:4 位基座模型约占 40 GB,因此单张 80 GB 的 H100 或 141 GB 的 H200 都有空间容纳适配器和激活值。基于 BF16 基座模型的 LoRA 可以装进单张 180 GB 的 B200,换用 288 GB 的 B300 则更宽裕。

8× H100 能对 70B 模型做全参数微调吗?

采用标准的 AdamW 混合精度训练时,单台服务器做不到:训练状态超过 1 TB,而 8× H100 只有 640 GB。您可以在 8× H100 上做 LoRA;如需全参数微调,请换用 8× B300,或采用精简方案的 8× B200。

与全参数微调相比,LoRA 的效果够用吗?

对于许多指令微调和领域适配任务,在所有线性层上应用 LoRA 是一个效果强、成本又低得多的基线方案。如果数据和预算都充足,请先在您自己的评测集上比较两者,再决定是否投入全参数微调。

70B 模型的 LoRA 适配器有多大?

作用于所有线性投影层、秩为 16 的适配器约有 2.07 亿个参数,BF16 精度下约 0.4 GB,因此您可以保留多个版本,并在推理部署时随时切换。

独享 GPU,按月计费

整卡 GPU US$449/月起,含 root 权限和流量,支持加密货币支付。

查看 GPU 与价格 用显存计算器估算所需 GPU

部署 GPU 服务器

本月即可用上您的 GPU 服务器。

选择配置,在同一表单中创建账户,并用余额支付首月费用。服务器在 10 分钟内交付。

  • 10 分钟内交付
  • 任何月份均可取消
  • 加密货币支付,最高加赠 50%

登录 FullGPU

管理您的 GPU 服务器、余额和账单。

首次使用 FullGPU? 创建账户