news 2026/9/26 10:11:30

Model Optimizer FAR3D ONNX 后训练量化实战:INT8/FP8 编码器 + TensorRT 11.1 部署与 Argoverse 2 精度评估

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Model Optimizer FAR3D ONNX 后训练量化实战:INT8/FP8 编码器 + TensorRT 11.1 部署与 Argoverse 2 精度评估

【免费下载链接】Model-Optimizer

A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning models for downstream deployment frameworks like TensorRT-LLM, TensorRT, vLLM, etc. to optimize inference speed.

项目地址:https://gitcode.com/GitHub_Trending/te/Model-Optimizer
点击查看免费下载

本文基于 Model Optimizer 仓库中的 FAR3D 示例(examples/onnx_ptq/far3d),完整介绍一套面向自动驾驶 3D 目标检测场景的端到端 ONNX 量化工作流:将 FAR3D 的 VoVNet 图像编码器后训练量化为 INT8 或 FP8,解码器保持导出时的混合 FP16/FP32 精度,在 TensorRT 11.1 下构建引擎,并在 Argoverse 2 验证集上评估 mAP 与加速比。读完本文,你将掌握 FAR3D + Argoverse 2 环境搭建、元数据与校准数据准备、AutoCast 与 Model Optimizer PTQ 量化、TensorRT 引擎构建以及精度/性能评估的完整实操方案。

一、工作流总览

FAR3D 示例属于 Model Optimizer 仓库中 ONNX 后训练量化(PTQ)工具链的一部分(参见 examples/onnx_ptq/README.md),与 PETR、BEVFormer 等自动驾驶感知示例并列。其核心思路是:

  1. 只量化编码器:FAR3D 中开销最大的 VoVNet 图像编码器被量化为 INT8 或 FP8;
  2. 保留解码器精度:解码器沿用 ONNX 导出时的混合 FP16/FP32 精度,避免引入额外误差;
  3. 两容器分工:evaluator 容器负责数据准备、ONNX 导出、校准数据生成与精度评估,ModelOpt 容器负责 AutoCast、量化与 TensorRT 引擎构建;
  4. 真实数据集评估:在 Argoverse 2 传感器验证集上以 mAP 和归一化加速比作为最终指标。

该工作流沿用了 NVIDIA DL4AGX 仓库中 FAR3D TensorRT 方案 的既定流程,本示例为其补充了 Model Optimizer 的量化与精度评估环节。

1.1 双容器分工与构建

PETR 与 FAR3D 共享同一个 Dockerfile 的两个构建目标(见 examples/onnx_ptq/Dockerfile):

  • evaluator 目标:基于 digest 固定的nvcr.io/nvidia/pytorch:22.06-py3,包含 OpenMMLab 旧版技术栈(mmcv-full==1.7.0、mmdet==2.28.2、torch==1.13.1+cu117,见 requirements-evaluator.txt),用于源设置、元数据、导出、校准与精度评估;
  • modelopt 目标:基于nvcr.io/nvidia/pytorch:26.07-py3,安装Model-Optimizer[onnx]与onnxruntime-gpu[cuda,cudnn]~=1.24.2,并强制固定tensorrt==11.1.0.106,用于 AutoCast、量化与 TensorRT 引擎构建。

从仓库根目录构建:

docker build --target evaluator -f examples/onnx_ptq/Dockerfile -t modelopt-onnx-evaluator . docker build --target modelopt -f examples/onnx_ptq/Dockerfile -t modelopt-onnx-trt11 .

两个容器需挂载同一个工作区,以便交接 ONNX 模型、校准 batch 与 TensorRT 引擎。容器内运行前需设置以下环境变量:

export CUDNN_LIB_DIR=/usr/lib/x86_64-linux-gnu/ export LD_LIBRARY_PATH="${CUDNN_LIB_DIR}:${LD_LIBRARY_PATH}"

注意:TensorRT 引擎必须在 TensorRT 11.1.0.106 上构建并在同一 GPU 架构上评估,序列化引擎不跨 TensorRT 版本或 GPU 架构移植(详见下文)。

二、第 1 步:准备 FAR3D 与 Argoverse 2

2.1 下载数据集并启动 evaluator

在宿主机下载 Argoverse 2 传感器验证集,然后以只读方式挂载原始数据集、以可写方式挂载工作区,启动 evaluator 容器:

docker run --rm -it --gpus=all --ipc=host \ --user "$(id -u):$(id -g)" -e HOME=/tmp \ -e USER="$(id -un)" -e LOGNAME="$(id -un)" \ -v /path/to/workspace:/workspace \ -v /path/to/av2_sensor:/data/av2:ro \ modelopt-onnx-evaluator

这里把原始数据集以:ro只读挂载,保证验证过程不会被意外改动。

2.2 克隆固定版本 DL4AGX 并打补丁

克隆 pinned 的 DL4AGX 树并应用其官方 FAR3D 导出补丁,这是整个工作流中唯一一处源码补丁:

git clone https://github.com/NVIDIA/DL4AGX.git /workspace/DL4AGX git -C /workspace/DL4AGX checkout 9f7b29104c253d5bc68334e7b83b3eecb72d4572 git -C /workspace/DL4AGX submodule update --init \ AV-Solutions/far3d-trt/dependencies/Far3D \ AV-Solutions/far3d-trt/dependencies/mmdetection3d git -C /workspace/DL4AGX/AV-Solutions/far3d-trt/dependencies/Far3D \ apply ../../patch/far3d.patch

同时下载 FAR3D 官方 checkpointiter_82548.pth。推荐的目录布局是:原始数据集保持只读,生成的元数据存到工作区:

/workspace/DL4AGX/AV-Solutions/far3d-trt/ ├── data/av2/ │ └── val -> /data/av2/val └── weights/iter_82548.pth
cd /workspace/DL4AGX/AV-Solutions/far3d-trt # 替换 DL4AGX 的数据集根目录符号链接,使生成的元数据保留在工作区 unlink data/av2 mkdir -p data/av2 weights ln -s /data/av2/val data/av2/val

这样data/av2/val指向只读的原始验证集,而prepare_metadata.py生成的元数据文件落在工作区,可在容器间共享。

三、第 2 步:元数据、ONNX 导出与校准数据

3.1 生成 Argoverse 2 验证元数据

prepare_metadata.py(examples/onnx_ptq/far3d/prepare_metadata.py)接收数据集根目录,做两件事:

  • 调用 DL4AGX 的create_av2_infos生成av2_val_infos.pkl(先写入av2_val_infos_mini.pkl再改名,避免覆盖冲突);
  • 遍历val/*/annotations.feather,为每帧标注追加log_id后合并,输出val_anno.feather。

该脚本对已存在的输出文件会主动抛出FileExistsError,拒绝覆盖,保证结果可复现。运行方式:

cd /workspace/DL4AGX/AV-Solutions/far3d-trt export PYTHONPATH=$PWD/dependencies/Far3D python /opt/Model-Optimizer/examples/onnx_ptq/far3d/prepare_metadata.py data/av2

3.2 导出 ONNX

使用 DL4AGX 自带的导出脚本,将 FAR3D 的编码器导出为far3d.encoder.onnx、解码器导出为far3d.decoder.onnx:

python tools/export_onnx.py \ dependencies/Far3D/projects/configs/far3d.py \ weights/iter_82548.pth

3.3 从数据加载器直接生成校准数据

prepare_calibration.py(examples/onnx_ptq/far3d/prepare_calibration.py)直接从验证集数据加载器生成校准 batch,无需临时 TensorRT 引擎或解码器校准数据。关键参数:

参数默认值说明
config—(必填)FAR3D 的 mmcv 配置文件路径
encoder_onnx—(必填)编码器 ONNX 路径,用于推导输入规格
output_dir—(必填)校准 batch 输出目录
--num-samples512期望生成的校准 batch 数
--sample-skip-interval20采样间隔,按(interval-1, num*interval, interval)步长取样

运行:

python /opt/Model-Optimizer/examples/onnx_ptq/far3d/prepare_calibration.py \ dependencies/Far3D/projects/configs/far3d.py \ far3d.encoder.onnx calibration/encoder

脚本底层用到了 examples/onnx_ptq/quantization_utils.py 中的NpzCalibrationWriter:它会先读取 ONNX 图输入(dtype 与形状),校验每次写入的 batch 与输入规格严格匹配(多一维或少一维都会报错),再以batch_0000.npz递增编号落盘,最终以batch_0000.npz至batch_0511.npz共 512 个文件结束。若最终数量不等于--num-samples,脚本会抛出RuntimeError,杜绝静默缺数据。

四、第 3 步:AutoCast 与 PTQ 量化、引擎构建

切换到modelopt-onnx-trt11容器并挂载同一工作区后,进入工程目录执行量化。

4.1 AutoCast:生成 FP16 对照基线

首先用 Model Optimizer 的 AutoCast 工具把编码器从 FP32 转换到混合 FP16,作为精度与性能的对照基线:

python -m modelopt.onnx.autocast \ --onnx_path far3d.encoder.onnx \ --output_path far3d.encoder.fp16.onnx \ --calibration_data calibration/encoder/batch_0000.npz \ --low_precision_type fp16 --keep_io_types --providers cuda:0 cpu

AutoCast 的 CLI 入口见 modelopt/onnx/autocast/main.py:

  • --low_precision_type(别名-t)指定目标精度,仅支持fp16/bf16,默认fp16;
  • --calibration_data(别名-d)支持单 batch NPZ 文件、多 batch NPZ 目录或 Polygraphy JSON,多 batch 会聚合统计量使转换决策更稳健;
  • --keep_io_types保留模型输入输出数据类型不变;
  • --providers cuda:0 cpu指定参考运行的执行提供者顺序;
  • 另有--nodes_to_exclude/--op_types_to_exclude/--nodes_to_include/--op_types_to_include等正则匹配选项,可精确控制哪些节点/算子留在 FP32 或强制进入低精度(见 convert.py 中convert_to_mixed_precision与autocast的实现,FP16 需要 opset ≥ 13,BF16 需要 opset ≥ 22)。

4.2 用 Model Optimizer 量化 VoVNet 编码器

quantize_vovnet.py(examples/onnx_ptq/quantize_vovnet.py)是 FAR3D/PETR 共用的 VoVNet 编码器量化脚本,内部调用modelopt.onnx.quantization.quantize:

for precision in int8 fp8; do python /opt/Model-Optimizer/examples/onnx_ptq/quantize_vovnet.py \ far3d.encoder.onnx calibration/encoder \ --precision "$precision" --output "far3d.encoder.${precision}.onnx" done

该脚本的关键实现点(源码可核对 quantize_vovnet.py):

  • --precision限定int8或fp8,默认int8;
  • 校准方法固定为max,执行提供者为["cuda:0", "cpu"];
  • 通过 quantization_utils.py 中的find_vovnet_nodes_to_exclude自动定位精度敏感节点:VoVNet OSA4_5 阶段以及 FPNlateral_convs下游的全部节点,将其从量化范围中排除(保持 FP16),从而保住小目标检测精度;
  • 使用NpzCalibrationReader流式读取batch_*.npz,避免一次性载入全部校准数据;
  • 量化在 ONNX 的临时副本上进行(temporary_onnx_copy),保证外部数据相对路径有效且不污染源模型。

补充说明:本仓库通用的 PTQ 入口是python -m modelopt.onnx.quantization(见 examples/onnx_ptq/README.md),支持fp8/int8/int4与max/entropy/awq_clip/rtn_dq等校准方法,并可用--calibrate_per_node对大模型做逐节点校准以降低显存占用;quantize_vovnet.py是针对 VoVNet 编码器做了节点排除与数据流适配的专用封装。

4.3 用 trtexec 构建引擎

对 FP16/INT8/FP8 三种编码器精度和解码器分别构建引擎:

for precision in fp16 int8 fp8; do trtexec --onnx="far3d.encoder.${precision}.onnx" \ --saveEngine="far3d.encoder.${precision}.engine" --skipInference done trtexec --onnx=far3d.decoder.onnx \ --saveEngine=far3d.decoder.mixed.engine --skipInference

两个要点:

  • TensorRT 11.1 使用 typed ONNX 图,因此无需--fp16或--stronglyTyped这类显式标记;
  • 序列化引擎不可跨 TensorRT 版本或 GPU 架构移植,换环境必须重新构建。

五、第 4 步:在 evaluator 容器中评估

用相同挂载重启modelopt-onnx-evaluator,对三种精度组合逐一评估:

cd /workspace/DL4AGX/AV-Solutions/far3d-trt export PYTHONPATH=$PWD/dependencies/Far3D for precision in fp16 int8 fp8; do python /opt/Model-Optimizer/examples/onnx_ptq/far3d/evaluate.py \ dependencies/Far3D/projects/configs/far3d.py \ "far3d.encoder.${precision}.engine" far3d.decoder.mixed.engine done

evaluate.py(examples/onnx_ptq/far3d/evaluate.py)的评估逻辑值得展开:

  • 编码器与解码器均通过 trt_runner.py 的TensorRTRunner加载:反序列化引擎、枚举 IO tensor 并映射到 torch dtype、分配 256 字节对齐的 CUDA 缓冲区,通过execute_async_v3在独立 CUDA 流上异步执行;
  • 解码器由Far3DDecoderRunner驱动:它维护memory_embedding、memory_reference_point、memory_egopose、memory_velo、memory_timestamp五组时序状态,跨场景切换时自动重置,并回读*_out输出更新状态,从而正确复现 FAR3D 的递归解码;
  • 每个 batch 的相机内外参、ego pose、lidar2img 等被搬到 CUDA 后送入 pipeline,编码器输出特征直接拼接进解码器输入;
  • 结果以LiDARInstance3DBoxes组织后交给dataset.evaluate,输出 3D 检测 mAP。

冒烟测试:加上--max-samples 2可只跑 2 个样本,同时覆盖递归解码器状态的执行路径。完整验证集包含 23,522 帧;如果未跑满整个数据集,脚本会打印已处理样本数并跳过数据集级指标。

六、参考精度与性能

文档给出的参考数据基于TensorRT 11.1.0.106、NVIDIA RTX 6000 Ada Generation GPU、512 个校准 batch测得:

6.1 精度(Argoverse 2 验证集 mAP)

EncoderDecodermAP
FP16Mixed FP16/FP320.241
INT8Mixed FP16/FP320.235
FP8Mixed FP16/FP320.239

可见 INT8 与 FP8 相对 FP16 基线的 mAP 损失都很小(约 0.002–0.006),其中 FP8 更接近 FP16。

6.2 性能(归一化到 FP16 管线)

性能测量仅在引擎层面进行,并归一化到 FP16 管线:每次比较 = 一次编码器前向 + 同一导出解码器前向,只改变编码器精度。测量方式为 TensorRT 11.1.0.106 + RTX 6000 Ada,每个引擎组件交错运行 5 次,取trtexec报告的 GPU Compute Time 中位数,关闭数据传输、开启 CUDA Graphs,各组件时间求和后再归一化,只报告加速比:

PipelineINT8 speedup vs. FP16FP8 speedup vs. FP16
FAR3D1.69x1.40x

七、仓库中的支撑实现与延伸阅读

  • 通用 ONNX PTQ 工具链与高级特性(逐节点校准、自定义算子量化、Autotune 等):examples/onnx_ptq/README.md;
  • 共享的校准数据读写与 VoVNet 精度敏感节点识别:examples/onnx_ptq/quantization_utils.py;
  • TensorRT 引擎的通用运行时封装(含状态张量与对齐缓冲区管理):examples/onnx_ptq/trt_runner.py;
  • 双目标 Dockerfile 与依赖固定:examples/onnx_ptq/Dockerfile、requirements-evaluator.txt;
  • 同类的自动驾驶 3D 检测量化示例:PETR、BEVFormer;
  • AutoCast 精度转换的实现细节:modelopt/onnx/autocast/main.py、convert.py。

适用前提与限制:本工作流依赖 digest 固定的两个容器镜像、TensorRT 11.1.0.106 与特定 GPU 架构,数据准备依赖 DL4AGX 的固定 commit(9f7b2910...)与官方导出补丁;换用其他 TensorRT 版本、GPU 或 FAR3D 版本时,需要重新验证量化配置与参考指标。

【免费下载链接】Model-Optimizer

A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning models for downstream deployment frameworks like TensorRT-LLM, TensorRT, vLLM, etc. to optimize inference speed.

项目地址:https://gitcode.com/GitHub_Trending/te/Model-Optimizer
点击查看免费下载
上一篇:FoundationDB 4.0 版本发布说明深度解析:API 400 新特性、fdbcli 增强与事务子系统优化
下一篇:BiliTools哔哩哔哩工具箱:2026年最强大的跨平台B站资源管理工具

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 10:09:25

Java 开发里的埋点是什么

目录 埋点采集什么信息 Java 里常见的埋点实现方式 1. 代码硬编码埋点(最基础) 2. AOP 切面埋点(Java 项目最常用!) 3. 中间件 / 异步埋点 4. 字节码埋点(探针,如 SkyWalking)…

作者头像 李华
网站建设 2026/9/26 10:08:27

Windows下用QEMU模拟ARM64安装银河麒麟V10全流程

不扯虚的,先说一下我为什么折腾这个。当时接了一个信创适配的活儿,软件要跑在银河麒麟V10上,CPU是鲲鹏的ARM架构。可我手边没有鲲鹏服务器,连一台ARM开发板都临时借不到,只有一台Windows笔记本。最开始想过上云&#x…

作者头像 李华
网站建设 2026/9/26 10:06:48

Java List查找对象性能优化:从contains到HashMap的O(1)方案

先聊个实际场景吧。有一次线上接口报警,CPU 被打满,十几个 QPS 就把服务拖到超时。查了半天,锅竟然出在一个 1 万大小的 List 上——有同事在循环里反复调用list.contains()去判断某个对象是否存在。1 万条数据不算大,但循环 500 …

作者头像 李华