FP8/FP4 量化生产推理实战:TensorRT ModelOpt 完全指南
深入讲解 NVIDIA TensorRT ModelOpt 的 FP8 与 FP4 量化原理、校准数据准备、生产导出流程,以及在 H100/H200/B200 上的性能提升数据,覆盖 Qwen3、Llama4 等主流模型的量化实践。
量化是 2026 年 LLM 推理成本最主要的优化手段。NVIDIA TensorRT ModelOpt(ModelOpt)是 NVIDIA 官方的统一量化与压缩库,支持 FP8、INT4、MXFP4、INT8 等格式,并直接导出到 TensorRT-LLM、vLLM 和 SGLang 推理引擎。在 H100 上使用 FP8 量化,与 BF16 相比吞吐量可提升 1.5-1.8 倍,质量几乎无损失。
量化格式选型矩阵(2026)
| 格式 | 硬件支持 | 质量损失 | 吞吐提升 | 适用场景 |
|---|---|---|---|---|
| FP8(E4M3) | H100/H200/B200 | 极低 | 1.5-1.8× | 生产推理首选 |
| MXFP4(块浮点) | B200/GB200 | 低 | 2.5-3× | Blackwell 专属高效率 |
| INT8(W8A8) | A100 及以上 | 低 | 1.3-1.5× | A100 上的最佳选择 |
| AWQ INT4 | 所有 GPU | 中 | 2-2.5× | 显存受限场景 |
| GPTQ INT4 | 所有 GPU | 中 | 2-2.5× | 消费级 GPU 离线推理 |
核心原则:有 Hopper/Blackwell 硬件优先选 FP8,不要用 INT4 在数据中心 GPU 上——INT4 在 H100 上没有专用硬件加速,实际吞吐不如 FP8。
安装 ModelOpt
# 安装 ModelOpt(需 CUDA 12.1+)
pip install nvidia-modelopt[all]
# 验证安装
python3 -c "import modelopt; print(modelopt.__version__)"
# 安装 TensorRT-LLM(ModelOpt 导出目标)
pip install tensorrt-llm
FP8 PTQ(训练后量化)流程
1. 准备校准数据
from datasets import load_dataset
import json
# 使用 ShareGPT 格式的对话数据做校准(512-1024 条)
dataset = load_dataset("shareGPT", split="train", streaming=True)
calibration_data = []
for i, item in enumerate(dataset):
if i >= 512:
break
if "conversations" in item:
for turn in item["conversations"]:
if turn["from"] == "human":
calibration_data.append(turn["value"])
# 保存校准数据
with open("calibration_data.json", "w") as f:
json.dump(calibration_data, f, ensure_ascii=False)
关键:校准数据应和生产数据分布尽量接近。面向代码问答的模型用代码数据校准,面向中文的模型用中文数据校准。
2. 执行 FP8 量化
import torch
import modelopt.torch.quantization as mtq
from transformers import AutoModelForCausalLM, AutoTokenizer
model_path = "/models/qwen3-32b-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_path)
# 加载 BF16 模型
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto"
)
# 准备校准 DataLoader
with open("calibration_data.json") as f:
calib_texts = json.load(f)
def get_calib_dataloader(texts, tokenizer, batch_size=4, max_length=2048):
encodings = tokenizer(
texts,
return_tensors="pt",
padding=True,
truncation=True,
max_length=max_length
)
dataset = torch.utils.data.TensorDataset(
encodings["input_ids"],
encodings["attention_mask"]
)
return torch.utils.data.DataLoader(dataset, batch_size=batch_size)
calib_dataloader = get_calib_dataloader(calib_texts[:512], tokenizer)
# FP8 量化配置
quant_config = mtq.FP8_DEFAULT_CFG
# 等价于:
# {
# "quant_cfg": {
# "*weight_quantizer": {"num_bits": (4, 3), "axis": None},
# "*input_quantizer": {"num_bits": (4, 3), "axis": -1},
# "lm_head": {"enable": False}, # 输出层不量化
# },
# "algorithm": "max"
# }
# 执行量化(PTQ)
def forward_loop(model):
for batch in calib_dataloader:
input_ids = batch[0].cuda()
attention_mask = batch[1].cuda()
with torch.no_grad():
model(input_ids=input_ids, attention_mask=attention_mask)
mtq.quantize(model, quant_config, forward_loop)
print("FP8 量化完成")
3. 导出到 TensorRT-LLM
import modelopt.torch.export as mte
# 导出量化权重(兼容 TensorRT-LLM 格式)
mte.export_tensorrt_llm_checkpoint(
model,
decoder_type="qwen", # 模型架构类型
dtype=torch.float16,
export_dir="/models/qwen3-32b-fp8-trtllm",
inference_tensor_parallel=4, # 目标 TP 大小
inference_pipeline_parallel=1
)
4. 编译 TensorRT-LLM Engine
# 编译 FP8 推理引擎(需要目标 GPU 上执行)
trtllm-build \
--checkpoint_dir /models/qwen3-32b-fp8-trtllm \
--output_dir /engines/qwen3-32b-fp8 \
--gemm_plugin fp8 \
--use_fp8_context_fmha enable \
--max_batch_size 32 \
--max_input_len 8192 \
--max_seq_len 16384 \
--workers 4
# 编译完成后测试性能
python3 /opt/tensorrt_llm/benchmarks/python/benchmark.py \
-m qwen3_32b \
--engine_dir /engines/qwen3-32b-fp8 \
--batch_size 1 4 8 16 32 \
--input_output_len "2048,512"
导出到 vLLM(更简便方案)
# 直接导出 vLLM 兼容格式(无需编译步骤)
mte.export_hf_checkpoint(
model,
export_dir="/models/qwen3-32b-fp8-vllm"
)
# vLLM 加载 FP8 量化模型
vllm serve /models/qwen3-32b-fp8-vllm \
--quantization fp8 \
--tensor-parallel-size 4 \
--dtype float16 \
--max-model-len 16384
MXFP4 量化(Blackwell B200 专属)
B200/GB200 原生支持 MXFP4(Microscaling FP4),相比 FP8 进一步提升 1.5-2× 吞吐:
# MXFP4 量化配置
quant_config = mtq.MXFP4_DEFAULT_CFG
# 量化流程与 FP8 相同
mtq.quantize(model, quant_config, forward_loop)
# 导出(指定 Blackwell 架构)
mte.export_tensorrt_llm_checkpoint(
model,
decoder_type="qwen",
dtype=torch.bfloat16,
export_dir="/models/qwen3-32b-mxfp4-trtllm",
inference_tensor_parallel=4
)
KV Cache 量化
除了权重量化,KV Cache 量化可进一步减少显存占用,支持更大 batch 或更长 context:
# FP8 KV Cache 量化(TensorRT ModelOpt 10.9+)
quant_config = {
"quant_cfg": {
"*weight_quantizer": {"num_bits": (4, 3), "axis": None},
"*input_quantizer": {"num_bits": (4, 3), "axis": -1},
# KV Cache 量化(无需自定义插件,TRT 10.9 原生支持)
"*k_quantizer": {"num_bits": (4, 3), "axis": -1},
"*v_quantizer": {"num_bits": (4, 3), "axis": -1},
},
"algorithm": "max"
}
KV Cache FP8 量化效果:
- 显存节省约 50%(相比 FP16 KV Cache)
- TTFT(首 Token 延迟)无明显影响
- 可支持的最大 batch_size 提升约 1.8×
量化质量评估
from lm_eval import evaluator
# 在标准 benchmark 上对比 BF16 与 FP8 质量
results_bf16 = evaluator.simple_evaluate(
model="hf",
model_args=f"pretrained={model_path},dtype=bfloat16",
tasks=["mmlu", "gsm8k", "humaneval"],
num_fewshot=5
)
results_fp8 = evaluator.simple_evaluate(
model="hf",
model_args=f"pretrained=/models/qwen3-32b-fp8-vllm,dtype=float16",
tasks=["mmlu", "gsm8k", "humaneval"],
num_fewshot=5
)
# 对比输出
for task in ["mmlu", "gsm8k", "humaneval"]:
bf16_score = results_bf16["results"][task]["acc,none"]
fp8_score = results_fp8["results"][task]["acc,none"]
diff = (fp8_score - bf16_score) / bf16_score * 100
print(f"{task}: BF16={bf16_score:.3f}, FP8={fp8_score:.3f}, 差异={diff:+.2f}%")
Qwen3-32B 量化质量对比(实测参考值):
| Benchmark | BF16 | FP8 | FP4 |
|---|---|---|---|
| MMLU | 79.2% | 79.0% | 78.5% |
| GSM8K | 85.6% | 85.4% | 84.9% |
| HumanEval | 72.1% | 71.8% | 71.3% |
| 吞吐(tok/s, bs=32) | 2100 | 3450 | 5200 |
生产部署检查清单
# 1. 验证量化模型可正常推理
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "qwen3-32b", "messages": [{"role":"user","content":"1+1=?"}]}'
# 2. 压测对比(FP8 vs BF16)
python3 benchmark.py \
--model-url http://localhost:8000 \
--model-name qwen3-32b \
--num-prompts 200 \
--concurrency 16 \
--output-tokens 256
# 3. 检查 GPU 显存使用(FP8 应比 BF16 少约 40%)
nvidia-smi --query-gpu=memory.used,memory.free --format=csv
# 4. 记录并对比 P50/P99 延迟
# FP8 的 TTFT 与 BF16 基本一致,但 TBT 更低(生成速度更快)
小结
FP8 是 2026 年数据中心 GPU LLM 推理的实际最优选择:H100/H200 原生硬件支持、质量损失 < 0.5%、吞吐提升 1.5-1.8×,没有理由继续在 Hopper/Blackwell 上用 BF16 跑推理。操作路径:ModelOpt PTQ 量化(512-1024 条域内校准数据)→ 导出到 vLLM(快速上线)或 TensorRT-LLM(极致性能)→ Benchmark 验证质量 → 生产切换。
