附录A 常用工具速查
附录A 常用工具速查
本附录是 AI Infra 工程师的案头手册。不会解释每个工具的设计哲学,但会给出最常用的命令和配置模板。
A.1 训练框架命令速查
A.1.1 PyTorch DistributedDataParallel (DDP)
DDP 是 PyTorch 内置的数据并行方案,适合单机多卡或小规模多机训练。
# 基本启动方式(单机 8 卡)
torchrun --nproc_per_node=8 train.py \
--batch_size=32 \
--learning_rate=1e-4
# 多机训练(2 台机器,每台 8 卡)
# 机器 0(主节点)
torchrun --nnodes=2 --nproc_per_node=8 \
--rdzv_id=exp01 \
--rdzv_backend=c10d \
--rdzv_endpoint=192.168.1.100:29500 \
train.py
# 机器 1(工作节点)
torchrun --nnodes=2 --nproc_per_node=8 \
--rdzv_id=exp01 \
--rdzv_backend=c10d \
--rdzv_endpoint=192.168.1.100:29500 \
train.py# DDP 标准代码模板
import torch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.data import DataLoader, DistributedSampler
def setup_ddp():
dist.init_process_group(backend="nccl")
torch.cuda.set_device(dist.get_rank())
def cleanup():
dist.destroy_process_group()
def train():
setup_ddp()
model = MyModel().cuda()
model = DDP(model, device_ids=[dist.get_rank()])
sampler = DistributedSampler(dataset, shuffle=True)
loader = DataLoader(dataset, batch_size=32, sampler=sampler)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
for epoch in range(num_epochs):
sampler.set_epoch(epoch) # ⚠️ 必须调用!
for batch in loader:
loss = model(batch)
loss.backward()
optimizer.step()
optimizer.zero_grad()
cleanup()
Warning常见坑
忘记调用 sampler.set_epoch(epoch) 会导致每个 epoch 的数据分配相同——模型学不到新东西。
A.1.2 DeepSpeed
DeepSpeed 提供了 ZeRO 优化器,是大模型训练的核心工具。
# 安装
pip install deepspeed
# 基本启动
deepspeed --num_gpus=8 train.py \
--deepspeed ds_config.json
# 多机启动
deepspeed --num_gpus=8 --num_nodes=2 \
--hostfile hostfile \
train.py --deepspeed ds_config.json// ds_config_zero2.json - ZeRO-2 配置
{
"zero_optimization": {
"stage": 2,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"allgather_partitions": true,
"allgather_bucket_size": 5e8,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 5e8,
"contiguous_gradients": true
},
"bf16": {
"enabled": true
},
"gradient_accumulation_steps": 4,
"train_batch_size": 256,
"train_micro_batch_size_per_gpu": 8
}// ds_config_zero3.json - ZeRO-3 配置(最激进的内存优化)
{
"zero_optimization": {
"stage": 3,
"offload_optimizer": { "device": "cpu" },
"offload_param": { "device": "cpu" },
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
},
"bf16": { "enabled": true },
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"gradient_accumulation_steps": "auto"
}A.1.3 Megatron-LM
Megatron-LM 是 NVIDIA 开发的大模型训练框架,支持 3D 并行。
# Megatron-LM 启动脚本(预训练 GPT 模型)
GPUS_PER_NODE=8
NNODES=2
MASTER_ADDR=192.168.1.100
MASTER_PORT=6000
DISTRIBUTED_ARGS="--nproc_per_node $GPUS_PER_NODE \
--nnodes $NNODES \
--master_addr $MASTER_ADDR \
--master_port $MASTER_PORT"
torchrun $DISTRIBUTED_ARGS pretrain_gpt.py \
--num-layers 32 \
--hidden-size 4096 \
--num-attention-heads 32 \
--seq-length 4096 \
--micro-batch-size 2 \
--global-batch-size 256 \
--tensor-model-parallel-size 4 \
--pipeline-model-parallel-size 2 \
--DDP-impl local \
--bf16 \
--use-flash-attn \
--optimizer adamw \
--lr 1e-4 \
--min-lr 1e-5 \
--weight-decay 0.1 \
--clip-grad 1.0 \
--train-iters 500000 \
--lr-decay-iters 320000 \
--data-path dataset/indices \
--vocab-file vocab.json \
--merge-file merges.txt \
--save checkpoints/gpt-7b \
--load checkpoints/gpt-7b \
--save-interval 5000 \
--log-interval 10A.1.4 PyTorch FSDP
FSDP 是 PyTorch 原生的 ZeRO-3 等价方案:
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
from torch.distributed.fsdp import ShardingStrategy, MixedPrecision
from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy
# FSDP 配置
fsdp_config = {
"sharding_strategy": ShardingStrategy.FULL_SHARD, # ZeRO-3 等价
"mixed_precision": MixedPrecision(
param_dtype=torch.bfloat16,
reduce_dtype=torch.bfloat16,
buffer_dtype=torch.bfloat16,
),
"auto_wrap_policy": size_based_auto_wrap_policy(min_num_params=1e6),
"cpu_offload": None, # 可配置 CPU offload
"limit_all_gathers": True, # 限制同时进行的 all-gather
}
model = MyModel()
model = FSDP(model, **fsdp_config)
# ⚠️ 保存 checkpoint 时需要特殊处理
# 全量保存:
with FSDP.state_dict_type(model, StateDictType.FULL_STATE_DICT):
state_dict = model.state_dict()
if dist.get_rank() == 0:
torch.save(state_dict, "checkpoint.pt")A.2 推理引擎命令速查
A.2.1 vLLM
# 安装
pip install vllm
# 基本启动(OpenAI 兼容 API)
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--tensor-parallel-size 2 \
--port 8000
# 使用 QLoRA
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--quantization awq \
--dtype half \
--max-model-len 4096 \
--gpu-memory-utilization 0.9 \
--tensor-parallel-size 1
# 性能调优参数
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-13b-chat-hf \
--tensor-parallel-size 2 \
--enable-chunked-prefill \ # 分块 prefill
--max-num-batched-tokens 8192 \ # 批处理 token 上限
--swap-space 4 \ # KV Cache swap(GB)
--gpu-memory-utilization 0.92# vLLM Python API
from vllm import LLM, SamplingParams
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
tensor_parallel_size=2,
max_model_len=4096,
gpu_memory_utilization=0.9,
enforce_eager=False, # 使用 CUDA Graph
)
sampling_params = SamplingParams(
temperature=0.7,
top_p=0.95,
max_tokens=512,
)
outputs = llm.generate(["你好,请介绍一下自己。"], sampling_params)A.2.2 NVIDIA Triton Inference Server
# config.pbtxt - Triton 模型配置
name: "llama-7b"
platform: "vllm"
max_batch_size: 0 # vLLM 内部处理 batching
input [
{
name: "prompt"
data_type: TYPE_STRING
dims: [1]
},
{
name: "max_tokens"
data_type: TYPE_INT32
dims: [1]
optional: true
}
]
output [
{
name: "text"
data_type: TYPE_STRING
dims: [1]
}
]
dynamic_batching {
preferred_batch_size: [4, 8, 16]
max_queue_delay_microseconds: 100000
}# Triton 启动
docker run --gpus all -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-v $(pwd)/model_repo:/models \
nvcr.io/nvidia/tritonserver:24.01-py3 \
tritonserver --model-repository=/models
# 性能测试
perf_analyzer -m llama-7b -u localhost:8000 \
--input-data prompt.json \
--concurrency-range 1:32:2A.2.3 TensorRT-LLM
# TensorRT-LLM 构建引擎(模型转换)
python build.py \
--model_dir ./llama-7b-hf \
--dtype float16 \
--use_gpt_attention_plugin \
--use_gemm_plugin \
--output_dir ./trt_engines/llama-7b \
--world_size 1 \
--tp_size 1 \
--pp_size 1 \
--max_batch_size 8 \
--max_input_len 2048 \
--max_output_len 512 \
--max_beam_width 1
# 启动 Triton + TensorRT-LLM 后端
python3 tensorrt_llm/serve.py \
--engine_dir ./trt_engines/llama-7b \
--tokenizer_dir ./llama-7b-hf \
--port 8000A.2.4 SGLang
# 安装
pip install sglang
# 启动服务
python -m sglang.launch_server \
--model-path meta-llama/Llama-2-7b-chat-hf \
--tp 2 \
--port 30000
# 使用 RadixAttention 加速多轮对话
python -m sglang.launch_server \
--model-path meta-llama/Llama-2-7b-chat-hf \
--tp 2 \
--enable-radix-attention \
--cache-queue-size 10000A.2.5 llama.cpp
# 下载并编译
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp && make -j
# 模型转换(GGUF 格式)
python convert.py models/llama-7b/ --outtype f16
# 量化
./quantize models/llama-7b/ggml-model-f16.gguf \
models/llama-7b/ggml-model-q4_k_m.gguf q4_k_m
# 推理(CLI)
./main -m models/llama-7b/ggml-model-q4_k_m.gguf \
-p "Once upon a time" \
-n 512 \
-t 8 # CPU 线程数
# 启动服务(OpenAI 兼容 API)
./server -m models/llama-7b/ggml-model-q4_k_m.gguf \
--port 8080 \
--ctx-size 4096 \
--threads 8A.2.6 Ollama
# 安装
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull llama3:8b
ollama pull mistral:7b
ollama pull qwen:7b
# 运行
ollama run llama3:8b
# 启动 API 服务
ollama serve # 默认 localhost:11434
# 自定义模型(Modelfile)
cat > Modelfile <<EOF
FROM llama3:8b
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
SYSTEM "你是一个专业的 AI 助手。"
EOF
ollama create my-assistant -f Modelfile
ollama run my-assistantA.3 集群管理工具速查
A.3.1 Kubernetes(GPU 调度)
# GPU Pod 定义
apiVersion: v1
kind: Pod
metadata:
name: llm-training
spec:
containers:
- name: trainer
image: pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime
resources:
limits:
nvidia.com/gpu: 8
memory: 512Gi
requests:
nvidia.com/gpu: 8
memory: 512Gi
volumeMounts:
- name: data
mountPath: /data
- name: dshm # 共享内存(DataLoader 需要)
mountPath: /dev/shm
volumes:
- name: data
persistentVolumeClaim:
claimName: training-data
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 128GiA.3.2 Slurm
# Slurm 提交训练任务
sbatch --job-name=llm-train \
--partition=gpu-h100 \
--nodes=4 \
--gres=gpu:H100:8 \
--ntasks-per-node=8 \
--cpus-per-task=16 \
--mem=512G \
--time=72:00:00 \
--output=logs/%j.out \
train.slurm
# train.slurm 脚本
#!/bin/bash
#SBATCH --job-name=llm-train
module load cuda/12.1
module load nccl/2.18
source activate llm-env
# 获取分配的节点
srun hostname | sort > hostfile
torchrun \
--nnodes=$SLURM_JOB_NUM_NODES \
--nproc_per_node=8 \
--rdzv_backend=c10d \
--rdzv_endpoint=$(head -1 hostfile):29500 \
train.py --deepspeed ds_config.json
# 交互式分配
salloc --partition=gpu-h100 --nodes=2 --gres=gpu:H100:8 --time=4:00:00A.3.3 Volcano(K8s 批调度)
# Volcano Job 定义
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: llm-training-job
spec:
minAvailable: 2
schedulerName: volcano
policies:
- event: PodEvicted
action: RestartJob
tasks:
- replicas: 2
name: trainer
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime
resources:
limits:
nvidia.com/gpu: 8
command:
- torchrun
- --nnodes=2
- --nproc_per_node=8
- train.py
restartPolicy: OnFailureA.4 监控与调试工具速查
A.4.1 NVIDIA Nsight Systems
# 系统级性能分析
nsys profile \
--output=train_profile \
--trace=cuda,nvtx,osrt,cudnn,cublas \
--stats=true \
python train.py
# 生成报告
nsys stats train_profile.nsys-rep
# GUI 查看
nsys-ui train_profile.nsys-repA.4.2 NVIDIA Nsight Compute
# 单 kernel 分析
ncu --set full \
--target-processes all \
--output kernel_profile \
python train.py
# 只分析最耗时的 kernel
ncu --kernel-name regex:".*attention.*" \
--launch-skip 10 \
--launch-count 5 \
python train.pyA.4.3 PyTorch Profiler
from torch.profiler import profile, record_function, ProfilerActivity
# 基础用法
with profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
record_shapes=True,
profile_memory=True,
with_stack=True,
) as prof:
for step, batch in enumerate(loader):
if step >= 5: # 采样前几步即可
break
loss = model(batch)
loss.backward()
optimizer.step()
prof.step() # ⚠️ 必须调用
# 打印结果
print(prof.key_averages().table(
sort_by="cuda_time_total",
row_limit=20,
))
# 导出 Chrome Trace(可视化)
prof.export_chrome_trace("trace.json")
# 检查通信开销
print(prof.key_averages(group_by_input_shape=True).table(
sort_by="self_cpu_memory_usage",
row_limit=10,
))A.4.4 NCCL Tests
# AllReduce 带宽测试
mpirun -np 8 \
--bind-to none \
./build/all_reduce_perf -b 8 -e 128M -f 2 -g 8
# AllGather 带宽测试
mpirun -np 8 \
./build/all_gather_perf -b 1K -e 64M -f 2 -g 8
# Point-to-Point 带宽测试(检查 NVLink / IB)
./build/sendrecv_perf -b 4 -e 128M -f 2 -g 1
# 多机 AllReduce 测试
mpirun -np 16 \
-H node1:8,node2:8 \
-bind-to none \
-x NCCL_SOCKET_IFNAME=eth0 \
-x NCCL_IB_HCA=mlx5 \
./build/all_reduce_perf -b 1M -e 128M -f 2 -g 8# NCCL 调试环境变量
export NCCL_DEBUG=INFO # 打印详细日志
export NCCL_DEBUG_SUBSYS=ALL # 所有子系统日志
export NCCL_NET_GDR_LEVEL=PHB # GPUDirect RDMA 级别
export NCCL_IB_TIMEOUT=22 # IB 超时
export NCCL_IB_RETRY_CNT=7 # IB 重试次数
export NCCL_SOCKET_NTHREADS=4 # Socket 线程数
export NCCL_NSOCKS_PERTHREAD=4 # 每线程 Socket 数
Tip调试流程建议
遇到多机训练问题时的标准排查顺序:(1) 检查网络连通性 ping + nc -zv; (2) 检查 GPU 可见性 nvidia-smi; (3) 运行 NCCL test 确认带宽; (4) 检查防火墙/IB 配置; (5) 最后才是看代码。
小结
本附录列出了 AI Infra 工程师最常用的工具命令。几点使用建议:
- 不要死记命令——理解原理,善用
--help和文档。 - 建立自己的工具脚本库——把常用组合封装成脚本。
- 关注工具版本——AI Infra 工具更新极快,升级前务必看 changelog。
- 性能基准要自己跑——不要完全依赖官方 benchmark,你的硬件和模型组合是唯一的。
延伸阅读
- PyTorch 分布式训练文档: https://pytorch.org/tutorials/beginner/dist_overview.html
- DeepSpeed 文档: https://www.deepspeed.ai/
- Megatron-LM GitHub: https://github.com/NVIDIA/Megatron-LM
- vLLM 文档: https://docs.vllm.ai/
- NVIDIA Nsight 文档: https://docs.nvidia.com/nsight-systems/
- NCCL 文档: https://docs.nvidia.com/deeplearning/nccl/
- Volcano 项目: https://volcano.sh/en/docs/