性能优化 #
优化目标 #
text
┌─────────────────────────────────────────────────────────────┐
│ 性能优化维度 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 显存优化: │
│ ├── 降低显存占用 │
│ ├── 训练更大模型 │
│ └── 使用更大批次 │
│ │
│ 速度优化: │
│ ├── 加速训练 │
│ ├── 缩短实验周期 │
│ └── 提高迭代效率 │
│ │
│ 推理优化: │
│ ├── 加速推理 │
│ ├── 降低延迟 │
│ └── 提高吞吐量 │
│ │
└─────────────────────────────────────────────────────────────┘
显存优化 #
显存分析 #
text
显存占用组成:
├── 模型参数
│ └── FP32: 参数量 × 4 字节
│ └── FP16: 参数量 × 2 字节
│
├── 梯度
│ └── 与参数量相同
│
├── 优化器状态
│ └── Adam: 参数量 × 8 字节(FP32)
│ └── Adam 8-bit: 参数量 × 2 字节
│
├── 激活值
│ └── 取决于批次大小和序列长度
│
└── 临时缓存
└── 中间计算结果
量化训练 #
python
from transformers import BitsAndBytesConfig
4-bit 量化:
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto"
)
8-bit 量化:
bnb_config = BitsAndBytesConfig(
load_in_8bit=True,
)
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto"
)
text
量化效果对比:
FP32(无量化):
├── 7B 模型:28GB
├── 13B 模型:52GB
└── 70B 模型:280GB
FP16(半精度):
├── 7B 模型:14GB
├── 13B 模型:26GB
└── 70B 模型:140GB
8-bit 量化:
├── 7B 模型:7GB
├── 13B 模型:13GB
└── 70B 模型:70GB
4-bit 量化:
├── 7B 模型:3.5GB
├── 13B 模型:6.5GB
└── 70B 模型:35GB
梯度检查点 #
python
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./results",
gradient_checkpointing=True,
)
或直接在模型上启用:
model.gradient_checkpointing_enable()
text
梯度检查点原理:
├── 不保存所有激活值
├── 需要时重新计算
├── 时间换空间
└── 显存减少 30-50%
适用场景:
├── 显存不足
├── 大模型训练
├── 长序列训练
└── 单卡训练
梯度累积 #
python
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=1,
gradient_accumulation_steps=16,
)
text
梯度累积效果:
├── 减少显存峰值
├── 模拟大批次训练
├── 不影响模型效果
└── 训练时间略增
推荐设置:
├── 小显存:batch_size=1, accumulation=16-32
├── 中显存:batch_size=4, accumulation=4-8
└── 大显存:batch_size=8, accumulation=2-4
优化器选择 #
python
标准 AdamW:
training_args = TrainingArguments(
output_dir="./results",
optim="adamw_torch",
)
8-bit AdamW:
training_args = TrainingArguments(
output_dir="./results",
optim="adamw_8bit",
)
Paged AdamW 8-bit:
training_args = TrainingArguments(
output_dir="./results",
optim="paged_adamw_8bit",
)
text
优化器显存对比(7B 模型):
AdamW(FP32):
├── 参数:14GB
├── 梯度:14GB
├── 优化器状态:112GB
└── 总计:140GB
AdamW 8-bit:
├── 参数:14GB
├── 梯度:14GB
├── 优化器状态:28GB
└── 总计:56GB
节省:84GB(60%)
混合精度训练 #
python
FP16 混合精度:
training_args = TrainingArguments(
output_dir="./results",
fp16=True,
)
BF16 混合精度:
training_args = TrainingArguments(
output_dir="./results",
bf16=True,
)
text
混合精度优势:
├── 显存减少约 50%
├── 训练速度提升约 2x
├── 保持精度
└── 硬件要求:
├── FP16:所有 GPU
└── BF16:Ampere+ GPU
训练加速 #
Flash Attention #
python
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto",
use_flash_attention_2=True,
)
text
Flash Attention 优势:
├── 注意力计算加速 2-4x
├── 显存占用减少
├── 支持更长序列
└── 需要 Ampere+ GPU
DeepSpeed #
python
ds_config = {
"train_batch_size": 16,
"gradient_accumulation_steps": 4,
"optimizer": {
"type": "AdamW",
"params": {
"lr": 2e-4,
}
},
"fp16": {
"enabled": True,
},
"zero_optimization": {
"stage": 2,
}
}
training_args = TrainingArguments(
output_dir="./results",
deepspeed=ds_config,
)
text
DeepSpeed ZeRO 阶段:
ZeRO-1:
├── 分片优化器状态
├── 显存减少约 4x
└── 通信开销小
ZeRO-2:
├── 分片优化器状态和梯度
├── 显存减少约 8x
└── 通信开销中等
ZeRO-3:
├── 分片所有状态
├── 显存减少约 N 倍(N=GPU 数量)
└── 通信开销大
FSDP #
python
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./results",
fsdp="full_shard auto_wrap",
fsdp_config={
"fsdp_auto_wrap_policy": "TRANSFORMER_BASED_WRAP",
"fsdp_sharding_strategy": "FULL_SHARD",
},
)
text
FSDP 优势:
├── PyTorch 原生支持
├── 完全分片数据并行
├── 显存效率高
└── 适合超大模型
多卡训练 #
python
单机多卡:
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=4,
num_train_epochs=3,
)
多机多卡:
torchrun --nproc_per_node=8 \
--nnodes=4 \
--node_rank=0 \
--master_addr="10.0.0.1" \
--master_port=12345 \
train.py
text
多卡训练策略:
数据并行(DP):
├── 复制模型到每张卡
├── 分割数据
├── 简单直接
└── 显存效率低
分布式数据并行(DDP):
├── 每张卡独立模型
├── 同步梯度
├── 效率高
└── 推荐使用
完全分片数据并行(FSDP):
├── 分片模型参数
├── 显存效率最高
└── 适合超大模型
推理优化 #
模型量化 #
python
动态量化:
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
model_name,
load_in_8bit=True,
device_map="auto"
)
静态量化:
from optimum.onnxruntime import ORTQuantizer
from optimum.onnxruntime.configuration import AutoQuantizationConfig
quantizer = ORTQuantizer.from_pretrained(model_name)
qconfig = AutoQuantizationConfig.avx2(is_static=False, per_channel=False)
quantizer.quantize(save_dir="./quantized-model", quantization_config=qconfig)
模型剪枝 #
python
import torch.nn.utils.prune as prune
def prune_model(model, amount=0.3):
for name, module in model.named_modules():
if isinstance(module, torch.nn.Linear):
prune.l1_unstructured(module, name='weight', amount=amount)
return model
model = prune_model(model, amount=0.3)
知识蒸馏 #
python
from transformers import AutoModelForCausalLM, AutoTokenizer
teacher_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-72B")
student_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-7B")
def distillation_loss(teacher_logits, student_logits, temperature=2.0):
from torch.nn.functional import kl_div, log_softmax, softmax
teacher_probs = softmax(teacher_logits / temperature, dim=-1)
student_log_probs = log_softmax(student_logits / temperature, dim=-1)
return kl_div(student_log_probs, teacher_probs, reduction='batchmean') * (temperature ** 2)
推理引擎 #
text
┌─────────────────────────────────────────────────────────────┐
│ 推理引擎对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ vLLM │
│ ├── 最快推理速度 │
│ ├── PagedAttention │
│ ├── 连续批处理 │
│ └── 推荐用于生产 │
│ │
│ TGI (Text Generation Inference) │
│ ├── Hugging Face 出品 │
│ ├── 功能完善 │
│ ├── 易于部署 │
│ └── 生产级方案 │
│ │
│ TensorRT-LLM │
│ ├── NVIDIA 出品 │
│ ├── 极致优化 │
│ ├── 需要 TensorRT │
│ └── 最高性能 │
│ │
│ llama.cpp │
│ ├── C++ 实现 │
│ ├── CPU 推理 │
│ ├── 跨平台 │
│ └── 边缘设备 │
│ │
└─────────────────────────────────────────────────────────────┘
python
vLLM 示例:
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2-7B")
sampling_params = SamplingParams(temperature=0.7, top_p=0.95, max_tokens=100)
outputs = llm.generate(["你好,请介绍一下自己。"], sampling_params)
性能监控 #
训练监控 #
python
import torch
def monitor_training():
print(f"GPU 显存已用: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")
print(f"GPU 显存缓存: {torch.cuda.memory_reserved() / 1024**3:.2f} GB")
print(f"GPU 显存最大: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
在训练循环中调用:
for batch in train_dataloader:
outputs = model(**batch)
loss = outputs.loss
loss.backward()
if step % 100 == 0:
monitor_training()
性能分析 #
python
import torch.profiler as profiler
with profiler.profile(
activities=[
profiler.ProfilerActivity.CPU,
profiler.ProfilerActivity.CUDA,
],
schedule=profiler.schedule(wait=1, warmup=1, active=3, repeat=2),
on_trace_ready=profiler.tensorboard_trace_handler('./logs'),
record_shapes=True,
profile_memory=True,
) as prof:
for batch in train_dataloader:
outputs = model(**batch)
loss = outputs.loss
loss.backward()
optimizer.step()
prof.step()
print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
优化策略 #
按场景选择 #
text
单卡小显存(<16GB):
├── QLoRA(4-bit 量化)
├── 梯度检查点
├── 小批次 + 梯度累积
├── 8-bit 优化器
└── 混合精度
单卡大显存(>32GB):
├── LoRA(大 rank)
├── Flash Attention
├── 中等批次
└── 混合精度
多卡训练:
├── DDP(2-4 卡)
├── FSDP(4+ 卡)
├── DeepSpeed ZeRO
└── 梯度检查点(可选)
超大模型(>70B):
├── DeepSpeed ZeRO-3
├── FSDP
├── 模型并行
└── CPU offloading
优化优先级 #
text
1. 显存优化(必须):
├── 量化训练
├── 梯度检查点
└── 梯度累积
2. 速度优化(推荐):
├── 混合精度
├── Flash Attention
└── 优化器选择
3. 分布式优化(可选):
├── DDP
├── FSDP
└── DeepSpeed
4. 推理优化(部署时):
├── 模型量化
├── 推理引擎
└── 批处理
常见问题 #
显存仍然不足 #
text
解决方案:
1. 进一步量化
- 使用 4-bit 量化
- 双重量化
2. 减小模型
- 使用更小的基座模型
- 减小 LoRA rank
3. 减小批次
- batch_size=1
- 增加 gradient_accumulation
4. 使用 CPU offloading
- DeepSpeed ZeRO-Offload
- FSDP CPU offload
训练速度慢 #
text
解决方案:
1. 启用混合精度
fp16=True 或 bf16=True
2. 使用 Flash Attention
use_flash_attention_2=True
3. 增大批次
在显存允许的情况下
4. 使用更快的数据加载
- 预取数据
- 多线程加载
5. 减少日志频率
logging_steps=100
下一步 #
现在你已经掌握了性能优化技巧,接下来学习 文本分类实战,开始实际项目!
最后更新:2026-04-05