orin部署教程1——yolo26-pose/CTR-GCN/PoseC3D的FP16量化

文章目录

一 前言

文中涉及的代码需等我整理好后再给出。

二 Jetson Orin 深度学习量化部署与算力评测通用教程:以 AGX Orin 上 YOLO26-Pose + CTR-GCN / PoseC3D 为完整实战

适用对象:第一次接触 Jetson、TensorRT、ONNX、FP16/INT8、边缘端性能分析和姿态动作识别的开发者。
通用目标:建立一套可迁移到 Jetson AGX Orin、Orin NX、Orin Nano,以及检测、分类、分割、姿态、时序动作识别等其他算法的部署方法。
完整实战环境:Jetson AGX Orin、JetPack 5.1.2、L4T R35.4.1、CUDA 11.4、TensorRT 8.5.2.2、Python 3.8。
完整实战任务:使用 YOLO26-Pose 提取人体关键点,再用 CTR-GCN 或 PoseC3D 判断 kicking / not_kicking

文档版本说明:本教程中的命令以当前板端环境 JetPack 5.1.2 / L4T 35.4.1 / TensorRT 8.5.2 为准。NVIDIA 最新 TensorRT 文档中的部分参数已经变化,例如 TensorRT 10.x 将 --workspace 改为 --memPoolSize。遇到差异时,应优先执行本机 trtexec --help,并查看本文提供的 TensorRT 8.x 归档文档,不要直接照抄最新版命令。

0. 先分清:哪些内容通用,哪些内容只适用于当前板子或算法

分类:整篇教程的适用范围说明。第一次阅读时建议先看完本章,再决定哪些命令可以照抄。

同一条“部署命令”通常同时受到四层因素影响:

通用深度学习部署方法
        ↓
Jetson / Orin 平台能力
        ↓
JetPack、L4T、CUDA、TensorRT 具体版本
        ↓
模型架构、输入输出、预处理和当前业务逻辑

因此,不能把“在某台 AGX Orin 上跑通的命令”理解成所有 Orin 和所有模型都能原样运行。正确做法是先判断命令属于哪一层。

0.1 本文使用的五种标签

标签含义换板子或换算法时怎么处理
[通用方法]与具体 Orin 和模型无关的方法论通常可以直接复用,例如建立 FP32 基线、ONNX 合法性检查、数值一致性验证
[Linux 通用]常见 Linux 系统都可使用unamelscpupidstattimedf;是否安装需自行确认
[Jetson 通用]Jetson 平台提供的工具tegrastatsnvpmodeljetson_clocks;其他桌面 GPU 不适用
[版本特定]参数或 API 依赖 JetPack/TensorRT/PyTorch 版本必须先查本机版本和对应归档文档,如 TRT 8.x 的 --workspace
[算法/项目特定]依赖模型结构、张量形状、类别、阈值或业务调度不能照抄;必须按新模型重写 wrapper、预处理、后处理或调度逻辑

0.2 本教程各章节的适用范围

章节主要分类换其他 Orin换其他算法
1 完整部署流程[通用方法] + 当前项目示例可复用流程可复用流程,替换模型步骤
2 模型架构[算法特定]与板子无关必须重新阅读新算法官方说明
3 输入输出[通用概念] + [算法特定]概念可复用shape、layout、dtype 必须重查
4~5 精度选择[通用方法]可复用可复用,但敏感层和精度风险不同
6 环境检查[Linux/Jetson 通用] + [版本特定]命令大多可复用与算法无关,框架包检查需替换
7 YOLO 导出[算法特定] + [版本特定]同算法可参考非 Ultralytics 模型不能照抄
8 CTR-GCN 导出[算法/项目特定]同算法可参考wrapper 和输入构造必须重写
9 数值一致性[通用方法] + CTR-GCN 示例方法可复用比较脚本的输入输出部分要改
10 实时接入[项目特定]可能需要适配性能和摄像头基本必须按新算法改写
11 PoseC3D[算法特定]同算法可参考其他算法不能照抄热图 pipeline
12 INT8[通用方法] + [算法特定校准]方法可复用校准输入和精度指标必须重做
13 性能公式[通用方法]直接复用直接复用
14~15 Orin监控[Jetson 通用] + 解析器版本差异可复用,字段可能变化与算法无关,可复用
16~18 公平对比和报告[通用方法]直接复用直接复用,替换业务指标
19 故障混合先判断版本和环境是否相同只采用与现象匹配的部分
20 交付清单[通用方法]直接复用直接复用
21 迁移指南[通用方法]直接使用直接使用

0.3 可以直接复用的“骨架流程”

无论部署的是检测、分类、分割、姿态、语音、Transformer 还是动作识别,下面这条流程通常都成立:

1. 记录目标板系统与软件版本
2. 保存原框架精度和性能基线
3. 明确真实输入 shape / dtype / layout / 预处理
4. 导出中间格式(通常是 ONNX)
5. 检查 ONNX 并在可用后端验证输出
6. 在目标设备和目标 TensorRT 版本上构建 engine
7. 使用相同真实输入比较原模型与 engine 输出
8. 接入完整应用,分开统计预处理、推理和后处理
9. 关闭显示、保存和 debug,采集稳定态性能与功耗
10. 再做 FP16、INT8、剪枝或调度优化

这十步是本教程最核心、最通用的部分。

0.4 不能直接复用的内容

下列内容只要换了算法,通常就必须重新确认:

  • 输入数量、输入名称和 shape;
  • NCHWNHWCNCTHW、骨架图等 layout;
  • RGB/BGR、归一化均值方差、resize、letterbox、裁剪;
  • 动态 batch、动态分辨率和动态序列长度;
  • 输出是 logits、概率、框、mask、关键点还是 token;
  • NMS、softmax、阈值、标签映射和时序平滑;
  • 是否包含 TensorRT 不支持的算子或自定义插件;
  • INT8 校准样本到底是原始数据还是预处理后的张量;
  • 正确性指标是 Top-1、mAP、mIoU、OKS、F1、召回率还是事件级误报率。

下列内容只要换了 Orin 或 JetPack,通常就必须重新确认:

  • 支持的 JetPack/L4T 版本;
  • CUDA、cuDNN、TensorRT 和 Python 版本;
  • trtexec 参数和 Python API;
  • 可用内存、GPU频率、DLA数量与功耗模式;
  • TensorRT engine 是否需要在新设备上重新构建;
  • tegrastats 字段名称和功耗电源轨;
  • PyTorch、torchvision、MMCV 等 wheel 是否与 aarch64 和 CUDA 匹配。

0.5 三个最容易混淆的“通用与特定”边界

边界一:ONNX 是通用格式,但导出代码不是完全通用

torch.onnx.export() 的思想可复用,但每个模型的 wrapper、dummy input 和动态维度不同。CTR-GCN 的 (1, 1, 2, 100, 17, 3) 不能拿去导出图像分类模型。

边界二:trtexec 是通用工具,但参数随版本变化

--onnx--saveEngine--loadEngine 的用途较稳定;工作区、精度约束、动态 shape 和 profiling 参数可能随 TensorRT 版本变化。始终先运行:

trtexec --help
python -c "import tensorrt as trt; print(trt.__version__)"

边界三:tegrastats 可测所有 Jetson 应用,但不能直接给出模型 TOPS

它能告诉你 GPU 忙碌度、内存带宽、CPU、RAM、温度和功耗;它不知道“某个模型理论执行了多少有效 FLOPs/TOPS”。模型计算量需要模型分析工具或算子级 profiling,实际板端压力则用 tegrastatstrtexec、Nsight Systems 和应用日志综合判断。


快速导航:我现在要做什么,应看哪份官方资料?

下面这张表适合在实际操作时快速查阅。本文负责把项目步骤串起来;官方资料负责解释工具的完整参数和版本规则。

你现在要做的事情优先查看的官方资料适用说明
确认 JetPack 5.1.2 自带哪些 CUDA/TensorRT 版本NVIDIA JetPack 5.1.2 Release Notes与本教程环境直接对应
安装或补装 JetPack 5.1.2 组件NVIDIA JetPack 5.1.2 Installation Guideapt/SDK Manager 相关操作
理解 YOLO26-Pose 的关键点输出Ultralytics Pose Task关键点、训练、验证、预测、导出
把 YOLO26-Pose 导出为 TensorRTUltralytics TensorRT Integrationformat=engine、FP16、INT8 等
查看 Ultralytics 全部导出参数Ultralytics Export Modeimgszhalfint8dynamic
在 Jetson 上安装和部署 UltralyticsUltralytics NVIDIA Jetson GuideJetson 环境与 TensorRT 部署
使用 ByteTrack/BoT-SORT 进行多目标跟踪Ultralytics Track ModePose 模型同样支持视频跟踪
理解 CTR-GCN 的网络设计CTR-GCN 官方代码库 / ICCV 2021 原论文图结构、通道拓扑细化、时序建模
理解 PoseC3D 的热图输入和模型结构MMAction2 PoseC3D READMEPoseC3D 官方实现与模型表
用自己的数据训练 PoseC3DMMAction2 PoseC3D Custom Dataset Tutorial标注、关键点提取、训练流程
理解 MMAction2 的骨架数据格式MMAction2 Customize Datasetkeypointkeypoint_score、PoseDataset
把 PyTorch 模型导出成 ONNXPyTorch ONNX Tutorial官方导出流程;旧版 PyTorch 需结合本教程脚本
检查 ONNX 图是否合法ONNX Checker APIonnx.checker.check_model()
用 ONNX 构建 TensorRT engineTensorRT trtexec Command Reference最新参数总览;TRT 8.x 参数以本机帮助为准
理解 TensorRT 8.x 的完整开发流程TensorRT 8.6.1 Archived Developer Guide与 TensorRT 8.5 接近,适合本项目参考
查看 TensorRT 8.x 到 10.x 参数差异Migrating trtexec from TensorRT 8.x to 10.x防止照抄新版参数
做 FP16/INT8 和混合精度TensorRT Quantization Workflows最新 PTQ/QAT/Q-DQ 思路
在 TensorRT 8.x 编写 INT8 calibratorTensorRT 8.6.1 IInt8Calibrator API适合 JetPack 5.x 的旧式校准接口
trtexec 测延迟和吞吐TensorRT Performance BenchmarkingLatency、Throughput、CUDA Graph 等
看懂 tegrastats 的 RAM/CPU/EMC/GR3DJetson Linux R35.4.1 Tegrastats Utility与当前 L4T 版本直接对应
固定 Orin 功耗模式和时钟Jetson Orin Power and Performancenvpmodeljetson_clocks、功率与频率
做 CPU/GPU 时间线级分析NVIDIA Nsight Systems User Guide定位 CPU 等 GPU、kernel launch、同步等问题
查询 cv2.imshow/HighGUI 行为OpenCV HighGUI Reference窗口、imshowwaitKey
使用独立显示进程Python multiprocessingspawn、Queue、Event、Process
减少跨进程整帧复制Python Shared Memory后续可把 Queue 升级为共享内存
先确认手上是哪款 Jetson、哪个 L4T/JetPackJetPack Archive / Jetson Linux Software Packages先执行本文第6章系统信息命令,再选择匹配的归档文档
查询其他 Jetson/Orin 型号NVIDIA Jetson Modules比较模块、内存和平台定位;具体功耗模式仍查对应 L4T 文档
判断当前 TensorRT 与系统是否兼容TensorRT Support Matrix先选择本机 TensorRT 版本;不要默认最新版适用于旧 JetPack
判断 engine 能否跨设备或跨版本使用TensorRT Engine CompatibilityJetPack 上通常应在目标设备/目标软件栈重建并验证 engine
换成其他 PyTorch 算法导出 ONNXPyTorch torch.onnx Documentation通用导出入口;dummy input、dynamic shape、wrapper 按新模型修改

阅读原则:项目命令以本文和本机软件版本为准;概念、API 语义和完整参数以官方文档为准。对于 TensorRT,尤其要先分清自己使用的是 8.x、10.x 还是更高版本。


1. 先看结论:完整部署流程

分类:[通用方法],流程可迁移;图中的模型名称和输入处理属于 [算法/项目特定]

本项目推荐的部署顺序如下:

训练好的 PyTorch 模型
        │
        ├── YOLO26-Pose .pt
        │       ↓
        │   TensorRT FP16 .engine
        │
        ├── CTR-GCN best.pth + resolved_config.py
        │       ↓
        │      ONNX
        │       ↓
        │   TensorRT FP16 .engine
        │
        └── PoseC3D checkpoint/config
                ↓
          姿态热图输入 ONNX
                ↓
          TensorRT FP16 .engine

完整推理链路:

视频 / 摄像头
    ↓
YOLO26-Pose TensorRT FP16
    ↓
人体框 + 17 个关键点 + 关键点置信度
    ↓
ByteTrack 分配人物 ID
    ↓
按人物 ID 维护时序骨架历史
    ↓
┌──────────────────────┬────────────────────────┐
│ CTR-GCN              │ PoseC3D                │
│ 骨架图序列            │ 骨架转时空热图          │
│ 图卷积 + 时间卷积      │ 3D CNN / SlowOnly      │
└──────────────────────┴────────────────────────┘
    ↓
kicking / not_kicking 概率

性能测试分成两种:

  1. 模型单体测试:只测 CTR-GCN engine 或 PoseC3D engine。
  2. 完整链路测试:测视频读取、YOLO、跟踪、预处理、动作模型、Python 调度和整板功耗。

正式比较时,必须同时给出这两种结果。


2. 系统架构与每个模型在做什么

分类:[算法特定]。换其他算法时应查看新模型论文、官方仓库和框架配置。

2.1 为什么不能只用动作分类模型

CTR-GCN 和 PoseC3D 都不是直接读取原始视频画面的模型。它们需要人体姿态数据,因此需要先运行 YOLO26-Pose。

YOLO26-Pose 的作用是回答:

  • 画面里有几个人?
  • 每个人在哪里?
  • 鼻子、肩、肘、腕、髋、膝、踝等 17 个关键点在哪里?
  • 每个关键点有多可信?

动作模型的作用是回答:

  • 这一段连续骨架运动是不是踢腿?

因此二者是前后级关系,不是替代关系。

2.2 为什么需要 ByteTrack

YOLO 每帧都检测人,但单独的检测结果不知道“这一帧的人”和“上一帧的人”是不是同一个人。

ByteTrack 会给每个人分配连续 ID,例如:

第 1 帧:人物 ID=3
第 2 帧:人物 ID=3
第 3 帧:人物 ID=3

这样程序才能为 ID=3 单独保存连续 20~100 帧的骨架历史。

2.3 CTR-GCN 为什么这样设计

CTR-GCN 把人体骨架视为一张图:

  • 每个关节是一个节点;
  • 骨骼连接是边;
  • 连续帧构成时间维度;
  • 节点特征是 (x, y, score)

它重点学习:

  • 膝盖与脚踝的相对运动;
  • 髋—膝—踝的空间关系;
  • 动作随时间如何展开;
  • 不同关节之间的动态关联。

优点:

  • 输入张量小;
  • 模型参数较少;
  • 通常比热图 3D CNN 更省内存和算力;
  • 适合边缘设备。

风险:

  • 非常依赖关键点质量;
  • 遮挡导致关键点漂移时,信息会直接丢失;
  • 只看骨架,不看箱子、车门、环境等视觉上下文。

2.4 PoseC3D 为什么这样设计

PoseC3D 不直接把关节当图节点,而是把每个关键点变成二维高斯热图,再沿时间堆叠成三维时空体。

例如某个膝盖的位置不是一个点,而是一小团高斯响应:

关键点坐标 (x, y)
    ↓
二维热图 H×W
    ↓
连续 T 帧堆叠
    ↓
C×T×H×W 的时空体
    ↓
3D CNN

它的优点:

  • 对小范围关键点抖动通常更鲁棒;
  • 3D 卷积可以学习局部时空运动纹理;
  • 关键点轻微偏差不会像纯坐标模型那样直接改变数值关系。

代价:

  • 热图尺寸远大于骨架坐标;
  • CPU 生成热图可能很耗时;
  • 3D 卷积计算量和显存带宽压力更大;
  • 完整链路延迟通常高于 CTR-GCN。

2.5 为什么本项目给 CTR-GCN 加动作完成候选检测

当前 CTR-GCN 实时程序不是每帧都调用动作模型,而是先通过已有关键点判断“腿是否踢出并收回”,只有出现候选时才调用 CTR-GCN。

这样设计的目的:

  • 避免每帧重复运行动作模型;
  • 降低整机平均 GPU 使用率;
  • 将连续分类结果转化为一次性踢腿事件;
  • 更适合“踢一下触发一次开门”的业务逻辑。

需要注意:

这种事件驱动调度会显著降低整机平均功耗,但它属于调度优化,不等于 CTR-GCN 模型本身一定快了同样比例。


3. 输入、输出和张量形状基础

分类:张量、shape、dtype、layout 是 [通用概念];本章具体 shape 是 [算法/项目特定]

3.1 什么是张量

张量可以理解为多维数组。

常见维度字母:

字母含义
B / NBatch,批量大小
CChannel,通道数或特征数
TTime,时间帧数
HHeight,高度
WWidth,宽度
MPerson,最多人数
VVertex / Joint,关节数

3.2 YOLO26-Pose 输入输出

典型输入:

原始 BGR 图像:H×W×3
    ↓ letterbox/resize
640×640×3
    ↓ 转 RGB、归一化、转 NCHW
1×3×640×640

典型输出经 Ultralytics 后处理后包括:

boxes.xyxy      [人数, 4]
boxes.conf      [人数]
boxes.id        [人数]        # 启用跟踪时
keypoints.data  [人数, 17, 3]

关键点最后一维:

[x, y, confidence]

COCO 17 点索引:

0 nose
1 left_eye
2 right_eye
3 left_ear
4 right_ear
5 left_shoulder
6 right_shoulder
7 left_elbow
8 right_elbow
9 left_wrist
10 right_wrist
11 left_hip
12 right_hip
13 left_knee
14 right_knee
15 left_ankle
16 right_ankle

3.3 CTR-GCN 输入输出

MMAction2 原始骨架数据常用格式:

keypoint       [M, T, V, 2]
keypoint_score [M, T, V]

其中:

  • M:人数;
  • T:帧数;
  • V=17:COCO 关键点数;
  • 坐标通道是 x、y;
  • score 是关键点置信度。

经过验证 pipeline 后,当前项目导出的实际输入:

[1, 1, 2, 100, 17, 3]

含义:

B=1
num_clips=1
M=2
T=100
V=17
C=3,即 x、y、score

输出:

logits [1, 2]

类别约定:

0 = kicking
1 = not_kicking

logits 不是概率,需要 softmax:

probability = torch.softmax(logits, dim=1)

3.4 PoseC3D 输入输出

PoseC3D 原始输入也是骨架:

keypoint       [M, T, 17, 2]
keypoint_score [M, T, 17]

但在送进模型前,会生成关键点热图:

关键点序列
    ↓ GeneratePoseTarget
pose heatmap
    ↓ 格式化
[B, C, T, H, W]

C 可能是:

  • 17 个关键点热图;
  • 或关键点 + limb 热图;
  • 实际通道数必须根据配置文件确认。

输出通常也是:

logits [B, 2]

不要在教程里硬编码 PoseC3D 热图形状。应先读取配置和实际 engine 绑定信息。


4. FP32、FP16、INT8 到底是什么

分类:[通用方法]。适用于绝大多数推理模型,但硬件支持和收益取决于目标设备。

4.1 FP32

FP32 是 32 位浮点数。

特点:

  • 数值范围和精度较高;
  • 训练最常用;
  • 模型占用内存较大;
  • 推理速度通常慢于 FP16/INT8。

一个 FP32 数值占 4 字节。

4.2 FP16

FP16 是 16 位浮点数,一个数占 2 字节。

理论上相较 FP32:

  • 权重内存约减半;
  • 内存传输量下降;
  • 可使用 Tensor Core 或半精度指令;
  • 通常加速明显;
  • 精度一般下降较小。

风险:

  • 有效数字更少;
  • 数值范围更窄;
  • 某些层可能溢出或精度下降;
  • TensorRT 通常会采用混合精度,而不是强制所有层都 FP16。

4.3 INT8

INT8 使用 8 位整数表示激活和权重。

一个数占 1 字节,相比 FP32 理论存储量是四分之一。

潜在收益:

  • 模型更小;
  • 内存带宽更低;
  • 支持 INT8 的硬件上吞吐更高;
  • 功耗可能下降。

风险:

  • 必须把浮点范围映射到有限整数范围;
  • 校准数据不代表真实场景时,精度可能明显下降;
  • 姿态关键点模型对量化误差可能敏感;
  • 关键点误差会进一步传递给动作模型;
  • 最终分类阈值可能需要重新选择。

4.4 参数精度、计算精度和接口精度不是一回事

运行 trtexec 时看到:

Input(s)s format: fp32
Output(s)s format: fp32

不代表 engine 内部全部使用 FP32。

可能情况是:

接口输入:FP32
内部计算:FP16
接口输出:FP32

这样可以减少调用方转换麻烦,同时让内部层使用低精度加速。

4.5 常见误解

误解 1:FP16 就一定快 2 倍

不一定。实际速度还受以下因素影响:

  • 算子是否支持 Tensor Core;
  • 模型是不是内存带宽受限;
  • 预处理是否占主要时间;
  • Python 和跟踪是否成为瓶颈;
  • batch 是否为 1;
  • TensorRT 是否进行了层融合。

误解 2:GR3D 50% 等于使用 50% TOPS

错误。

GR3D 是 GPU 忙碌时间比例,不是实际执行了多少整数运算或浮点运算。

误解 3:engine 后缀写了 FP16,就能证明全部层是 FP16

错误。文件名只是人为命名。真正要通过构建日志、layer info 和性能验证确认。


5. 为什么优先做 FP16,而不是直接 INT8

分类:[通用方法]。先建立正确 FP16 基线再做 INT8,适用于大多数工程部署。

推荐顺序:

PyTorch FP32 基线
    ↓
ONNX FP32
    ↓
TensorRT FP16
    ↓
数值一致性验证
    ↓
完整视频准确率验证
    ↓
性能和功耗基线
    ↓
INT8 校准和验证

这样做的好处:

  1. FP16 通常容易成功;
  2. 可以先验证 ONNX 和 TensorRT 转换链路是否正确;
  3. 若 INT8 精度下降,可以明确问题来自量化,而不是导出逻辑;
  4. 可以先判断 FP16 是否已经达到实时和功耗目标;
  5. 避免 YOLO 和动作模型同时 INT8 后无法定位误差来源。

推荐渐进实验:

A. YOLO FP16 + CTR-GCN FP16
B. YOLO INT8 + CTR-GCN FP16
C. YOLO FP16 + CTR-GCN INT8
D. YOLO INT8 + CTR-GCN INT8

每一步都重新测试关键点精度、动作召回率、误报率和阈值。


6. 环境准备、系统信息采集与 Conda 隔离

分类:包含 [Linux 通用]、[Jetson 通用]、[版本特定] 和 [项目特定] 内容,请按小节标签使用。

6.1 在任何 Jetson / Orin 上先采集系统信息

分类:前半部分是 [Linux 通用]nv_tegra_releasenvpmodeljetson_clockstegrastats[Jetson 通用];具体输出和参数是 [版本特定]

不要先猜“这块板应该是 JetPack 5 还是 6”,也不要仅凭设备商品名判断软件版本。先在目标板执行下面的命令并保存结果。

6.1.1 查询板卡型号和 CPU 架构

tr -d '\0' < /proc/device-tree/model; echo
uname -m
lscpu

常见解释:

  • aarch64:64位 ARM 架构,是 Orin 上正常的结果;
  • /proc/device-tree/model:识别 AGX Orin、Orin NX、Orin Nano 或开发套件;
  • lscpu:核数、在线 CPU、架构和缓存信息。

uname -m 是 Linux 通用命令;读取设备树型号主要面向嵌入式 Linux,具体字符串由板级设备树决定。

6.1.2 查询 Ubuntu、内核和 L4T

cat /etc/os-release
uname -a
cat /etc/nv_tegra_release
dpkg-query -W nvidia-l4t-core

其中:

  • /etc/os-release:Ubuntu 版本;
  • uname -a:Linux 内核和架构;
  • /etc/nv_tegra_release:Jetson Linux/L4T BSP 版本,是选择 Jetson Linux 归档文档的关键;
  • nvidia-l4t-core:用 Debian 包再次核对 L4T 版本。

NVIDIA 的 Jetson Linux 软件包文档明确建议通过 /etc/nv_tegra_release 检查当前软件版本:

注意:L4T/BSP 是板端系统最可靠的版本锚点。nvidia-jetpack 是元软件包,可能没有安装,或者系统只安装了部分 JetPack 组件,所以不能只看这个包。

6.1.3 查询 JetPack 元软件包

dpkg-query -W nvidia-jetpack 2>/dev/null || true
apt-cache policy nvidia-jetpack

如果查不到,不代表 CUDA/TensorRT 一定没有安装,只可能表示没有安装完整 nvidia-jetpack 元包。应继续逐项查询 CUDA、TensorRT 和 cuDNN。

JetPack 历史版本入口:

6.1.4 查询 CUDA

nvcc --version
readlink -f /usr/local/cuda
cat /usr/local/cuda/version.json 2>/dev/null || \
cat /usr/local/cuda/version.txt 2>/dev/null

还要在当前 Python 环境查看框架实际绑定的 CUDA:

python - <<'PY'
import torch
print('PyTorch:', torch.__version__)
print('PyTorch编译CUDA:', torch.version.cuda)
print('CUDA可用:', torch.cuda.is_available())
if torch.cuda.is_available():
    print('GPU:', torch.cuda.get_device_name(0))
    print('Compute Capability:', torch.cuda.get_device_capability(0))
PY

nvcc --version 显示系统 CUDA Toolkit;torch.version.cuda 显示当前 PyTorch 构建时使用的 CUDA 版本,两者概念不同。

6.1.5 查询 TensorRT 和 cuDNN

dpkg-query -W -f='${Package}\t${Version}\n' \
  'tensorrt*' 'libnvinfer*' 'python3-libnvinfer*' 'libcudnn*' \
  2>/dev/null | sort -u

python - <<'PY'
try:
    import tensorrt as trt
    print('TensorRT Python:', trt.__version__)
    print('TensorRT path:', trt.__file__)
except Exception as e:
    print('TensorRT Python不可用:', e)
PY

command -v trtexec || true
ls -l /usr/src/tensorrt/bin/trtexec 2>/dev/null || true

TensorRT 官方兼容矩阵:

TensorRT 归档文档入口:

6.1.6 查询当前 Python、Conda 和模型框架

echo "CONDA_PREFIX=$CONDA_PREFIX"
which python
python -V
python -m pip --version
conda info --base 2>/dev/null || true

一次性查看常用包:

python - <<'PY'
import importlib
import sys

print('Python:', sys.version)
print('Executable:', sys.executable)
for name in [
    'numpy', 'torch', 'torchvision', 'tensorrt', 'onnx',
    'onnxruntime', 'cv2', 'ultralytics', 'mmcv',
    'mmengine', 'mmaction'
]:
    try:
        m = importlib.import_module(name)
        print(name, getattr(m, '__version__', '<无版本字段>'), getattr(m, '__file__', ''))
    except Exception as e:
        print(name, '不可用:', e)
PY

换成其他算法时,把框架包名替换为对应框架,例如 TensorFlow、Paddle、Detectron2、Transformers 或自研包。

6.1.7 查询功耗模式和时钟

sudo nvpmodel -q
sudo jetson_clocks --show

用于跑性能测试时,通常还会执行:

sudo jetson_clocks
sudo jetson_clocks --show

这些命令是 Jetson 平台通用工具,但:

  • 各 Orin 型号的模式编号和功耗上限不同;
  • 最大时钟受当前 nvpmodel 模式限制;
  • 不应把 AGX Orin 的模式编号复制到 Orin NX/Nano;
  • 应查看与目标 L4T 和目标模块匹配的“Platform Power and Performance”章节。

当前 R35.4.1 Orin 文档:

6.1.8 查询 GPU、CPU、内存、温度和功耗实时状态

tegrastats --interval 1000

停止:

Ctrl+C

当前 R35.4.1 字段说明:

nvidia-smi 在不同 Jetson 软件栈中的支持情况不同,也不能替代 Jetson 的电源轨、EMC 和 SoC 监控。Jetson 性能采集优先使用 tegrastats

6.1.9 一键生成系统信息报告

教程压缩包提供:

collect_jetson_system_info.sh

运行:

chmod +x collect_jetson_system_info.sh
./collect_jetson_system_info.sh

或指定输出文件:

./collect_jetson_system_info.sh system_info_before_deployment.txt

这个脚本可以用于不同 Orin 和不同算法,因为它主要采集平台、软件栈和当前 Python 环境。换算法时无需改脚本;只需确保在目标算法的 Conda 环境中再运行一次,记录该环境的包版本。

6.2 当前实战板端环境

本项目当前验证环境:

硬件:Jetson AGX Orin Developer Kit
JetPack:5.1.2
L4T:R35.4.1
CUDA:11.4
TensorRT:8.5.2.2
Python:3.8

CTR-GCN 运行环境中已验证组合:

PyTorch:1.11.0
Torchvision:0.12.0a0
MMCV:2.1.0
MMEngine:0.10.7
MMAction2:1.2.0

YOLO 导出环境中已验证组合:

PyTorch:2.1.0a0+41361538.nv23.06
CUDA:11.4
Ultralytics:8.4.52

6.3 为什么当前项目分两个 Conda 环境

原因:

  • CTR-GCN/MMCV 可能依赖旧 PyTorch ABI;
  • YOLO26 导出需要更高版本的 PyTorch/Ultralytics;
  • 强行在一个环境里替换 Torch,可能导致 mmcv.ops 二进制不兼容;
  • pip 安装错误环境会破坏原有链路。

建议:

ctrgcn       # 完整运行、MMAction2、CTR-GCN、PoseC3D

yolo_export  # YOLO .pt 导出 TensorRT

6.4 每次安装前先确认 Python 和 pip

 echo "CONDA_PREFIX=$CONDA_PREFIX"
 python -c "import sys; print(sys.executable)"
 python -m pip --version
 conda info --base

安装包统一使用:

python -m pip install 包名

不要只输入:

pip install 包名

因为 pip 的 shebang 可能仍指向旧环境。

6.5 检查当前项目核心环境

python - <<'PY'
import torch
import torchvision
import numpy as np

print("Torch:", torch.__version__)
print("Torchvision:", torchvision.__version__)
print("NumPy:", np.__version__)
print("CUDA:", torch.version.cuda)
print("CUDA可用:", torch.cuda.is_available())

if torch.cuda.is_available():
    print("GPU:", torch.cuda.get_device_name(0))
    x = torch.randn(256, 256, device="cuda")
    y = x @ x
    torch.cuda.synchronize()
    print("CUDA计算正常:", y.shape)
PY

CTR-GCN 环境再检查:

python - <<'PY'
import mmcv
import mmcv.ops
import mmengine
import mmaction

print("MMCV:", mmcv.__version__)
print("MMEngine:", mmengine.__version__)
print("MMAction2:", mmaction.__version__)
print("mmcv.ops正常")
PY

7. YOLO26-Pose 导出 TensorRT FP16

分类:[Ultralytics/YOLO算法特定] + [TensorRT版本特定]。其他模型只能复用导出—验证的方法,不能照抄命令。

7.1 准备模型

假设权重:

models/yolo26n-pose.pt

进入 yolo_export 环境:

conda activate yolo_export
cd /media/orin2/45fd09e1-b992-4c00-9a54-232c1fb0e672/kicking/kick_action_orin_benchmark/models

7.2 先验证 .pt 模型能加载

python - <<'PY'
from ultralytics import YOLO

model = YOLO("yolo26n-pose.pt", task="pose")
print("模型加载成功")
print("任务类型:", model.task)
model.info()
PY

7.3 用一帧视频验证 CUDA 推理

python - <<'PY'
import cv2
from ultralytics import YOLO

video_path = "../out_06.mp4"
model_path = "yolo26n-pose.pt"

cap = cv2.VideoCapture(video_path)
ok, frame = cap.read()
cap.release()
if not ok:
    raise RuntimeError(f"无法读取视频:{video_path}")

model = YOLO(model_path, task="pose")
result = model.predict(
    source=frame,
    device=0,
    imgsz=640,
    conf=0.25,
    iou=0.70,
    verbose=True,
)[0]

print("检测人数:", len(result.boxes) if result.boxes is not None else 0)
print("关键点:", result.keypoints.data.shape if result.keypoints is not None else None)
PY

7.4 导出 FP16 engine

python - <<'PY'
from ultralytics import YOLO

model = YOLO("yolo26n-pose.pt", task="pose")

output = model.export(
    format="engine",
    device=0,
    imgsz=640,
    batch=1,
    half=True,
    dynamic=False,
    workspace=4,
    simplify=False,
)

print("导出结果:", output)
PY

重命名:

mv yolo26n-pose.engine \
   yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine

命名建议包含:

模型名_设备_JetPack_TensorRT_精度_输入尺寸_batch.engine

7.5 TensorRT 8.5 与 NumPy 1.24 的 np.bool 问题

若报错:

AttributeError: module 'numpy' has no attribute 'bool'

在导入 TensorRT/Ultralytics 前加:

import numpy as np
if "bool" not in np.__dict__:
    np.bool = np.bool_

也可以在当前环境创建:

SITE_PACKAGES=$(python -c 'import site; print(site.getsitepackages()[0])')
cat > "$SITE_PACKAGES/sitecustomize.py" <<'PY'
import numpy as np
if "bool" not in np.__dict__:
    np.bool = np.bool_
PY

7.6 验证 engine

python - <<'PY'
import numpy as np
if "bool" not in np.__dict__:
    np.bool = np.bool_

import cv2
from ultralytics import YOLO

engine = "yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine"
video = "../out_06.mp4"

cap = cv2.VideoCapture(video)
ok, frame = cap.read()
cap.release()
if not ok:
    raise RuntimeError("无法读取视频")

model = YOLO(engine, task="pose")
result = model.predict(frame, device=0, imgsz=640, verbose=True)[0]

print("Engine推理成功")
print("人数:", len(result.boxes) if result.boxes is not None else 0)
print("关键点:", result.keypoints.data.shape if result.keypoints is not None else None)
PY

7.7 Unknown embedded device 警告

AGX Orin 64GB + TensorRT 8.5 可能显示:

Unknown embedded device detected.
Using 59660MiB as the allocation cap...

这表示 TensorRT 使用检测到的内存作为分配上限,不是立即占用 59GB。只要最后 engine 构建成功并能推理,通常可以忽略。

7.8 Engine 可移植性

TensorRT engine 通常与以下内容绑定:

  • GPU 架构;
  • TensorRT 版本;
  • CUDA/JetPack 环境;
  • 构建时选择的 tactic。

因此推荐在最终部署的 AGX Orin 上构建,不要把其他 GPU 上生成的 engine 直接作为正式版本。


本章官方参考


8. CTR-GCN 从 PyTorch 导出 ONNX 和 TensorRT FP16

分类:ONNX/TensorRT 流程是 [通用方法];wrapper、shape 和 pipeline 是 [CTR-GCN/项目特定]

配套脚本:

scripts/export_ctrgcn_onnx.py
scripts/validate_ctrgcn_trt.py
scripts/realtime_ctrgcn_trt_fp16.py

将脚本复制到项目根目录:

cp scripts/*.py .

8.1 输入文件

output_online/runs/ctrgcn/seed_42/resolved_config.py
output_online/runs/ctrgcn/seed_42/best.pth
output_online/runs/ctrgcn/seed_42/result.json

8.2 为什么不能直接把 .pth 改名成 .engine

.pth 是 PyTorch 权重,依赖 Python、模型类和框架执行。

.engine 是 TensorRT 已优化的推理计划,包含:

  • 层融合;
  • kernel/tactic 选择;
  • 精度决策;
  • 显存规划;
  • 输入输出绑定。

必须经过:

PyTorch 模型 + 权重
    ↓
ONNX 计算图
    ↓
TensorRT engine

8.3 导出 ONNX

conda activate ctrgcn
cd /media/orin2/45fd09e1-b992-4c00-9a54-232c1fb0e672/kicking/kick_action_orin_benchmark

python export_ctrgcn_onnx.py \
  --config output_online/runs/ctrgcn/seed_42/resolved_config.py \
  --checkpoint output_online/runs/ctrgcn/seed_42/best.pth \
  --output models/ctrgcn_fp32_static.onnx \
  --device cpu \
  --skip-ort

脚本会:

  1. 注册 MMAction2 和 projects.ctrgcn.models
  2. 加载 config 与 checkpoint;
  3. 复用验证 pipeline;
  4. 构造真实格式输入;
  5. 提取 backbone + GCNHead;
  6. 导出 logits;
  7. 保存测试输入和参考输出。

生成:

models/ctrgcn_fp32_static.onnx
models/ctrgcn_fp32_static.input.npy
models/ctrgcn_fp32_static.json

预期输入:

skeleton [1, 1, 2, 100, 17, 3]

预期输出:

logits [1, 2]

8.4 查看 ONNX 输入输出

python - <<'PY'
import onnx

model = onnx.load("models/ctrgcn_fp32_static.onnx")

print("输入:")
for item in model.graph.input:
    dims = [
        d.dim_value if d.dim_value > 0 else d.dim_param
        for d in item.type.tensor_type.shape.dim
    ]
    print(item.name, dims)

print("输出:")
for item in model.graph.output:
    dims = [
        d.dim_value if d.dim_value > 0 else d.dim_param
        for d in item.type.tensor_type.shape.dim
    ]
    print(item.name, dims)
PY

8.5 构建 TensorRT FP16 engine

/usr/src/tensorrt/bin/trtexec \
  --onnx=models/ctrgcn_fp32_static.onnx \
  --saveEngine=models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
  --fp16 \
  --workspace=2048 \
  --buildOnly \
  2>&1 | tee ctrgcn_build_fp16.log

成功标志:

Engine built successfully
&&&& PASSED TensorRT.trtexec

8.6 单模型性能测试

/usr/src/tensorrt/bin/trtexec \
  --loadEngine=models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
  --warmUp=2000 \
  --duration=30 \
  --useSpinWait \
  2>&1 | tee ctrgcn_benchmark_fp16.log

重点看:

Throughput
Latency
GPU Compute Time
Enqueue Time
H2D Latency
D2H Latency

8.7 查看绑定信息

/usr/src/tensorrt/bin/trtexec \
  --loadEngine=models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
  --dumpLayerInfo \
  --profilingVerbosity=detailed \
  --iterations=1 \
  2>&1 | tee ctrgcn_engine_info.log
grep -E \
  "Input|Output|Binding|Latency|Throughput|GPU Compute" \
  ctrgcn_engine_info.log

9. CTR-GCN TensorRT 数值一致性验证

分类:比较同一输入的原框架与部署后端输出属于 [通用方法];脚本中的输入和类别解释是 [算法特定]

只生成 engine 不代表结果正确。必须使用相同输入比较 PyTorch 和 TensorRT。

python validate_ctrgcn_trt.py \
  --engine models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
  --input models/ctrgcn_fp32_static.input.npy \
  --metadata models/ctrgcn_fp32_static.json \
  --warmup 50 \
  --iterations 500

本项目一次实测结果:

输入数组:(1, 1, 2, 100, 17, 3) float32
输出:(1, 2) float32

PyTorch logits: [-2.3435175,  2.3578887]
TensorRT logits:[-2.3435402,  2.3579068]

logits最大绝对误差:2.26498e-05
概率最大绝对误差:3.63216e-07
类别一致:not_kicking
平均端到端调用耗时:约 6.43 ms

判断标准建议:

最终类别必须一致
logits最大绝对误差 < 0.05
真实视频事件结果基本一致

单个样本通过后,还要用多个真实样本验证:

  • kicking;
  • not_kicking;
  • 走路;
  • 抬腿但不踢;
  • 左腿/右腿;
  • 近距离/远距离;
  • 遮挡;
  • 多人。

10. 把 CTR-GCN TensorRT 接入实时程序

分类:[项目特定]。可借鉴 TensorRT runner、后端切换和进程隔离设计,但不能原样用于其他模型。

10.1 TensorRT 完整链路

python realtime_ctrgcn_trt_fp16.py \
  --source out_06.mp4 \
  --pose-model models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
  --action-backend tensorrt \
  --action-engine models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
  --no-show \
  --no-save-video

10.2 PyTorch 对照链路

python realtime_ctrgcn_trt_fp16.py \
  --source out_06.mp4 \
  --pose-model models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
  --action-backend pytorch \
  --checkpoint output_online/runs/ctrgcn/seed_42/best.pth \
  --no-show \
  --no-save-video

10.3 检查哪些结果

两种后端使用相同视频,比较:

踢出收回完成候选数
动作模型调用次数
脚踢事件数
触发帧位置
输出概率
平均处理FPS

10.4 为什么显示要独立进程

当前环境中已确认:

TensorRT 推理正常
cv2.imshow 单独运行正常
TensorRT + cv2.imshow 同一进程时段错误

因此演示模式使用:

推理主进程
    ↓ multiprocessing.Queue
显示子进程

这属于环境中 Qt/HighGUI 与 TensorRT/CUDA 原生库冲突的规避方案。

正式算力测试必须加:

--no-show --no-save-video

这样不会启动显示进程,也不会把进程通信和绘制开销算进核心算法。


本章官方参考


11. PoseC3D 的输入、热图和 TensorRT 部署

分类:[PoseC3D算法特定]。其他视频模型可能使用 RGB、光流、token 或不同序列布局。

11.1 当前 PoseC3D 完整链路

YOLO Pose关键点
    ↓
按人物维护 pose_history
    ↓
构造 MMAction2 sample
    ↓
PoseC3D test pipeline
    ↓
生成姿态热图
    ↓
TensorRT PoseC3D engine
    ↓
两类 logits / probability

11.2 PoseC3D 预处理主要做什么

典型步骤:

  1. 读取连续关键点与 score;
  2. 时间采样到固定长度;
  3. 坐标缩放、裁剪或归一化;
  4. 将每个关键点生成二维高斯热图;
  5. 按时间堆叠;
  6. 调整为 3D CNN 输入格式。

在性能分析中应拆分:

posec3d/sample_build
posec3d/pipeline_build
posec3d/preprocess
posec3d/h2d
posec3d/execute
posec3d/d2h
posec3d/total

其中热图生成常常是 CPU 端不可忽略的开销。

11.3 缓存 pipeline

不要每次动作推理都重新:

pipeline = Compose(config.test_pipeline)

应在 __init__ 中构建一次并缓存。

只有为了复现旧版低效行为时,才使用:

--rebuild-pose-pipeline

11.4 运行 PoseC3D 完整链路

示例:

python3 orin_algorithm_profiled.py \
  --video /absolute/path/out_06.mp4 \
  --input-mode throughput \
  --loop-video \
  --run-seconds 90 \
  --yolo-engine /absolute/path/models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
  --posec3d-engine /absolute/path/models/posec3d_trt-5.engine \
  --posec3d-config /absolute/path/configs/skeleton/posec3d/slowonly_r50_8xb16-u48-240e_ntu60-xsub-keypoint-2.py \
  --label-map /absolute/path/labels.txt \
  --no-web \
  --no-draw \
  --no-gpio \
  --profile \
  --profile-warmup 10

11.5 PoseC3D engine 单体测试

/usr/src/tensorrt/bin/trtexec \
  --loadEngine=models/posec3d_trt-5.engine \
  --warmUp=2000 \
  --duration=30 \
  --useSpinWait \
  2>&1 | tee posec3d_engine_benchmark.log

11.6 PoseC3D 从 PyTorch 到 TensorRT 的通用流程

不同 PoseC3D 配置的热图通道数和尺寸不同,因此不要直接复制 CTR-GCN 输入形状。

正确流程:

1. 加载配置和 checkpoint
2. 用真实 pose_history 运行 test pipeline
3. 打印 heatmap.shape
4. 保存 heatmap.npy
5. 用纯模型 wrapper 接受 heatmap tensor
6. torch.onnx.export
7. ONNX checker
8. trtexec --fp16
9. 相同 heatmap 比较 PyTorch/ONNX/TensorRT logits

导出 wrapper 的核心结构:

class PoseC3DExportWrapper(torch.nn.Module):
    def __init__(self, recognizer):
        super().__init__()
        self.backbone = recognizer.backbone
        self.cls_head = recognizer.cls_head

    def forward(self, heatmap):
        feature = self.backbone(heatmap)
        logits = self.cls_head(feature)
        return logits

实际调用方式必须根据当前 MMAction2 模型结构确认,不能盲目照搬。


本章官方参考


12. INT8 量化:收益、风险和正确顺序

分类:PTQ/QAT 方法是 [通用方法];校准输入、样本分布和精度指标是 [算法特定]

12.1 INT8 不是简单加 --int8

INT8 需要确定每层浮点值如何映射到整数范围。PTQ 通常需要校准数据。

错误校准会出现:

  • YOLO 框正常但关键点明显漂移;
  • 低置信关键点全部消失;
  • 膝盖/脚踝误差增大;
  • CTR-GCN/PoseC3D 概率分布变化;
  • 原来的 0.6309 阈值不再最优。

12.2 YOLO INT8 校准数据

校准图片应覆盖真实部署分布:

不同光照
白天/夜晚
近距离/远距离
人部分出画
腿部遮挡
拿箱子遮挡膝盖
运动模糊
单人/多人
踢腿/非踢腿
不同衣服和背景

不要只用训练集里最清晰的踢腿图片。

Ultralytics 的版本不同,INT8 导出参数可能略有差异。常见形式:

model.export(
    format="engine",
    int8=True,
    data="pose_calibration.yaml",
    imgsz=640,
    batch=1,
    device=0,
    workspace=4,
)

执行前先检查当前版本帮助和官方导出参数:

yolo export --help

12.3 CTR-GCN INT8 校准数据

CTR-GCN 校准数据不是图片,而是经过完全相同 pipeline 后的:

[1, 1, 2, 100, 17, 3] float32

校准集应包含多个 .npy

calib_0001.npy
calib_0002.npy
...

内容覆盖:

  • kicking / not_kicking;
  • 左腿 / 右腿;
  • 快踢 / 慢踢;
  • 遮挡;
  • 关键点缺失和低 score;
  • 走路、跑步、抬腿、转身等易误报动作;
  • 不同人数和人体尺度。

严禁使用随机张量作为正式校准集。

12.4 PoseC3D INT8 校准数据

PoseC3D 校准输入应是已经生成好的真实热图,而不是原始图片或关键点坐标。

必须复用同一 pipeline:

真实骨架
    ↓
与验证完全一致的 GeneratePoseTarget
    ↓
真实 heatmap tensor
    ↓
INT8 calibrator

12.5 INT8 验证项目

至少比较:

FP16 与 INT8 logits误差
最终类别一致率
kicking recall
not_kicking specificity
F1
误报次数/小时
触发阈值
端到端FPS
平均功耗
P95功耗
GR3D
EMC

12.6 是否值得 INT8

以下情况可能不值得:

  • FP16 已经满足帧率和功耗要求;
  • 动作模型实际每 100 帧只调用几次;
  • 整机开销主要在 YOLO;
  • CPU 预处理才是瓶颈;
  • INT8 使关键点或动作精度明显下降。

因此先测 FP16,再决定是否量化。


本章官方参考

注意:前两项是新版量化工作流,强调显式 Q/DQ;本项目 TensorRT 8.5 仍可使用 calibrator。两套方法不要混写成同一套命令。


13. 延迟、速度、吞吐量如何计算

分类:[通用方法]。可用于 Jetson、桌面 GPU、CPU、DLA 和其他推理后端。

13.1 FPS

FPS = 处理帧数 / 运行秒数

例如:

900 帧 / 45 秒 = 20 FPS

13.2 每帧耗时

每帧毫秒 = 1000 / FPS

例如:

20 FPS → 50 ms/帧
25 FPS → 40 ms/帧
50 FPS → 20 ms/帧

注意:平均 FPS 与平均单阶段延迟不是简单相加关系,因为 GPU 调用、CPU 工作和异步执行可能重叠。

13.3 Latency 与 Throughput

  • Latency:一次输入从开始到得到结果需要多久。
  • Throughput:单位时间最多处理多少次。

例如:

CTR-GCN一次完整调用 6.43 ms
理论串行上限 ≈ 1000 / 6.43 = 155.5 次/秒

但完整视频 FPS 还包含 YOLO 和其他处理,因此不会达到 155 FPS。

13.4 P50、P95、P99

假设采集 1000 次延迟:

  • P50:一半请求小于该值;
  • P95:95% 请求小于该值;
  • P99:99% 请求小于该值。

实时系统不能只看平均值。

例如:

平均 20 ms
P95 45 ms

说明偶尔会明显卡顿。

13.5 动作调用频率

每100帧动作调用次数
= 动作模型总调用数 / 总帧数 × 100

该指标对 CTR-GCN 非常重要。

例如:

1000帧只调用20次CTR-GCN
每100帧调用2次

即使单次动作推理是 6 ms,整机平均负担也很低。

13.6 单帧能耗

平均功率单位 W 等于 J/s。

因此:

每帧能耗 J/frame = 平均功率 W / FPS

例如:

平均功耗 30 W
平均速度 20 FPS
每帧能耗 = 30 / 20 = 1.5 J/frame

该指标适合比较不同方案的整体能效。

13.7 增量开销

测三组:

A. YOLO-only
B. YOLO + CTR-GCN
C. YOLO + PoseC3D

粗略估计:

CTR-GCN增量功耗 ≈ B平均功耗 - A平均功耗
PoseC3D增量功耗 ≈ C平均功耗 - A平均功耗

这是近似值,因为 GPU DVFS、并行重叠和温度会导致非线性,不能当作绝对精确分解。


本章官方参考


14. Orin 算力占用和功耗如何采集

分类:采集思想是 [通用性能方法]tegrastats/nvpmodel/jetson_clocks[Jetson通用]

配套脚本:

scripts/collect_orin_profile_generic.sh
scripts/analyze_orin_profile.py

复制并赋权:

cp scripts/collect_orin_profile_generic.sh .
cp scripts/analyze_orin_profile.py .
chmod +x collect_orin_profile_generic.sh

14.1 固定功耗模式和频率

sudo -v
sudo nvpmodel -q
sudo jetson_clocks
sudo jetson_clocks --show

PoseC3D 和 CTR-GCN 必须使用相同 nvpmodel 和频率状态。

不要一组开 jetson_clocks,另一组不开。

14.2 CTR-GCN 完整链路采集

./collect_orin_profile_generic.sh \
  --label ctrgcn_full_trt_fp16 \
  --interval-ms 200 \
  --warmup-seconds 3 \
  -- \
  python realtime_ctrgcn_trt_fp16.py \
    --source out_06.mp4 \
    --pose-model models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
    --action-backend tensorrt \
    --action-engine models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
    --no-show \
    --no-save-video

14.3 CTR-GCN engine 单体采集

./collect_orin_profile_generic.sh \
  --label ctrgcn_engine_trt_fp16 \
  --interval-ms 200 \
  --warmup-seconds 3 \
  -- \
  /usr/src/tensorrt/bin/trtexec \
    --loadEngine=models/ctrgcn_agx-orin_jp512_trt85_fp16.engine \
    --warmUp=2000 \
    --duration=30 \
    --useSpinWait

14.4 PoseC3D engine 单体采集

./collect_orin_profile_generic.sh \
  --label posec3d_engine_trt_fp16 \
  --interval-ms 200 \
  --warmup-seconds 3 \
  -- \
  /usr/src/tensorrt/bin/trtexec \
    --loadEngine=models/posec3d_trt-5.engine \
    --warmUp=2000 \
    --duration=30 \
    --useSpinWait

14.5 PoseC3D 完整链路采集

./collect_orin_profile_generic.sh \
  --label posec3d_full_trt_fp16 \
  --interval-ms 200 \
  --warmup-seconds 10 \
  -- \
  python3 orin_algorithm_profiled.py \
    --video /absolute/path/out_06.mp4 \
    --input-mode throughput \
    --loop-video \
    --run-seconds 90 \
    --yolo-engine /absolute/path/models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
    --posec3d-engine /absolute/path/models/posec3d_trt-5.engine \
    --posec3d-config /absolute/path/posec3d_config.py \
    --label-map /absolute/path/labels.txt \
    --no-web \
    --no-draw \
    --no-gpio \
    --profile \
    --profile-warmup 10

14.6 YOLO-only 基线

./collect_orin_profile_generic.sh \
  --label yolo_only_trt_fp16 \
  --interval-ms 200 \
  --warmup-seconds 10 \
  -- \
  python3 orin_algorithm_profiled.py \
    --video /absolute/path/out_06.mp4 \
    --input-mode throughput \
    --loop-video \
    --run-seconds 90 \
    --yolo-engine /absolute/path/models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine \
    --no-action \
    --no-web \
    --no-draw \
    --no-gpio \
    --profile \
    --profile-warmup 10

14.7 输出目录

orin_profile_runs/
└── 20260728_160000_ctrgcn_full_trt_fp16/
    ├── tegrastats.log
    ├── pidstat.log
    ├── app_stdout.log
    ├── app_stderr.log
    ├── system_info.txt
    ├── exit_code.txt
    ├── tegrastats_summary.csv
    ├── tegrastats_summary.json
    ├── profile_summary.json
    └── profile_summary.md

本章官方参考


15. GR3D、EMC、CPU、RAM、VDD_IN 等指标解释

分类:[Jetson通用]。不同 Jetson Linux 版本和模块可能显示不同字段或电源轨名称。

15.1 GR3D_FREQ

示例:

GR3D_FREQ 62%@[1098,1098]

通俗理解:

  • 62%:采样周期内 GPU 图形/计算引擎约 62% 时间在忙;
  • 1098:GPU 频率信息,单位通常 MHz;
  • 双值可能对应 GPU 频率域或设备输出格式。

它可以判断 GPU 忙不忙,但不能直接转换为 TOPS。

经验性解释:

平均 GR3D通俗判断
< 40%GPU负载较低
40%~75%中等负载
> 75%高负载
P95 ≥ 90%峰值阶段接近GPU饱和

这只是工程分类,不是硬件理论定义。

15.2 为什么 GR3D 不能直接换算 TOPS

理论 TOPS 是在特定数据类型、特定稠密度和理想硬件利用下的峰值运算能力。

实际程序中包括:

  • FP16、FP32 和整数混合;
  • 内存访问;
  • 分支;
  • kernel 启动间隙;
  • CPU 等待;
  • Tensor Core 与 CUDA Core 混用;
  • 不同算子利用率。

因此:

GR3D 50% ≠ 使用了50%的INT8 TOPS

正式报告建议写:

GPU平均忙碌度为 xx%,P95为 xx%。

不要写:

占用了 xx TOPS

除非有经过验证的硬件计数器和算子级 FLOPs 分析。

15.3 EMC_FREQ

EMC 是 External Memory Controller,外部内存控制器。

通俗理解:

GPU和CPU要从内存搬数据,EMC反映内存通道有多忙。

EMC 高可能来自:

  • 大热图;
  • 大量 frame.copy;
  • CPU/GPU 数据拷贝;
  • 视频解码;
  • 多进程传整帧;
  • 3D CNN 中间特征;
  • 多人并行。

经验性判断:

EMC P95判断
< 50%内存带宽压力较低
50%~85%中等
≥ 85%带宽压力较高

15.4 CPU 全核心平均占用

假设 Orin 有 12 个 CPU 核心,其中一个核心 100%,其他核心空闲:

全核心平均可能只有约 8.3%

因此只看 CPU 平均会掩盖单核瓶颈。

15.5 最忙 CPU 核心

如果:

最忙核心 P95 ≈ 100%
GR3D 平均只有 35%

说明程序可能是 CPU/调度受限,例如:

  • Python 循环;
  • ByteTrack;
  • PoseC3D 热图生成;
  • OpenCV 解码;
  • 队列调度;
  • 单线程后处理。

15.6 RAM

RAM used 是整板当前已使用内存,不完全等于算法进程独占。

它包含:

  • 操作系统;
  • 桌面;
  • Python;
  • CUDA/TensorRT;
  • 文件缓存;
  • 其他进程。

要看单进程内存,还要结合 pidstat -r

15.7 CUDA allocated 和 reserved

PyTorch 常见两个概念:

  • allocated:当前张量真正使用的显存;
  • reserved:PyTorch 缓存分配器向 CUDA 预留的显存池。

通常:

reserved >= allocated

不要把 reserved 全部理解成模型实际占用。

15.8 VDD_IN

VDD_IN 通常是板端总输入功率的重要口径。

示例:

VDD_IN 30000mW/28000mW

常见含义:

  • 当前功率;
  • 平均功率。

自动分析脚本会优先选择:

VDD_IN
POM_5V_IN
VIN_SYS_5V0

不会随意把多个分轨相加冒充总功耗。

15.9 温度和频率

温度升高可能触发降频,导致后半段测试变慢。

正式测试应:

  • 使用相同风扇模式;
  • 记录环境温度;
  • 预热后再统计;
  • 每组测试持续时间一致;
  • 检查是否发生 thermal throttling。

16. CTR-GCN 与 PoseC3D 如何公平对比

分类:控制变量和双口径比较是 [通用方法];模型名称和调度策略是 [项目示例]

必须分成两层。

16.1 模型本身公平对比

控制变量:

相同设备
相同nvpmodel
相同jetson_clocks状态
都使用TensorRT FP16
相同batch=1
相同预热时间
相同测试时长
关闭显示和保存

比较:

engine大小
GPU Compute Time
Latency P50/P95
Throughput
GR3D
EMC
平均功耗
峰值显存

这一层回答:

CTR-GCN 与 PoseC3D 模型本身谁更轻?

16.2 完整产品方案对比

保持各自实际调度:

CTR-GCN:完成候选后按需调用
PoseC3D:固定滑窗或固定间隔调用

比较:

端到端FPS
动作调用次数/100帧
GR3D平均/P95
CPU
EMC
平均/P95功耗
每帧能耗
准确率
召回率
误报率

这一层回答:

实际部署时哪套方案更省资源?

16.3 相同调用频率对比

为了消除调度差异,应额外做:

CTR-GCN和PoseC3D都每N帧调用一次

例如都每 24 帧调用一次。

这样回答:

在相同调用频率下,动作模型的增量代价是多少?

16.4 不能只比较 FPS

两个方案可能都达到视频输入上限 20 FPS:

PoseC3D:GPU 80%,20 FPS
CTR-GCN:GPU 35%,20 FPS

仅看 FPS 会认为一样,但 CTR-GCN 有更大算力余量。

因此必须同时报告 GR3D、功耗和 P95 延迟。


17. 推荐的完整实验矩阵

分类:矩阵设计方法可迁移;具体行项目是 [当前项目特定]

17.1 模型转换验证

编号模型后端目的
A1YOLO26-PosePyTorch原始正确性
A2YOLO26-PoseTRT FP16转换正确性
A3CTR-GCNPyTorch原始基线
A4CTR-GCNTRT FP16转换正确性
A5PoseC3DPyTorch/原始原始基线
A6PoseC3DTRT FP16转换正确性

17.2 模型单体性能

编号测试
B1YOLO engine trtexec
B2CTR-GCN engine trtexec
B3PoseC3D engine trtexec

17.3 完整链路性能

编号测试
C1YOLO-only
C2YOLO + CTR-GCN PyTorch
C3YOLO + CTR-GCN TRT FP16
C4YOLO + PoseC3D TRT FP16

17.4 调度对比

编号策略
D1CTR-GCN 原生事件驱动
D2PoseC3D 原生固定滑窗
D3两者统一每24帧调用

17.5 INT8 可选实验

编号YOLO动作模型
E1FP16FP16
E2INT8FP16
E3FP16INT8
E4INT8INT8

每次只改变一个变量。


18. 如何阅读自动生成的报告并下结论

分类:[通用方法],适用于其他 Orin 和算法;阈值只是经验性诊断,不是硬件官方上限。

自动报告:

profile_summary.md
profile_summary.json

终端会打印:

========== Orin 性能测试重点结论 ==========
- GPU(GR3D)平均忙碌度 xx%,P95 xx%。
- CPU全核心平均占用 xx%。
- 最忙CPU核心P95 xx%。
- EMC平均 xx%,P95 xx%。
- 板端平均功耗 xx W,P95 xx W,峰值 xx W。
- 完整链路平均吞吐 xx FPS。
- 动作模型每100帧调用 xx 次。
==========================================

18.1 典型结论模板:GPU余量较大

YOLO26-Pose + CTR-GCN TensorRT FP16 完整链路平均达到 20 FPS。
GPU GR3D 平均忙碌度为 38%,P95 为 61%,未出现持续GPU饱和。
最忙CPU核心P95为 72%,EMC P95为 45%。
说明当前20 FPS主要受输入视频节奏限制,板端仍有一定GPU和内存带宽余量。

18.2 典型结论模板:GPU瓶颈

完整链路平均吞吐为 18 FPS,GR3D平均为 82%,P95为 98%。
CPU最忙核心P95仅为 65%,EMC P95为 60%。
说明链路主要受GPU计算限制,继续提高输入帧率时首先会遇到GPU瓶颈。

18.3 典型结论模板:CPU瓶颈

GR3D平均仅为 42%,但最忙CPU核心P95达到 100%,端到端FPS为 16。
说明当前更可能受Python调度、跟踪或CPU预处理限制,而不是GPU算力不足。
应优先优化PoseC3D热图生成、Python循环、数据复制或跟踪逻辑。

18.4 典型结论模板:CTR-GCN 比 PoseC3D 更省资源

在相同YOLO engine、相同视频、相同功耗模式和FP16精度下:
CTR-GCN动作模型单次GPU计算时间低于PoseC3D,engine更小;
完整链路中CTR-GCN采用事件驱动,每100帧动作模型调用次数更少;
因此CTR-GCN方案的平均GR3D和平均整板功耗更低。
需要同时说明PoseC3D可能在关键点噪声和轻微漂移场景中具有更好的鲁棒性,最终选择不能只看算力。

18.5 报告中不应写的结论

不要写:

GR3D平均23%,所以使用了Orin 23%的275 TOPS。

正确写法:

GR3D平均忙碌度为23%,表示采样周期内GPU处于忙碌状态的时间比例较低。
该值不能直接换算为理论TOPS利用率。

19. 常见故障与解决方法

分类:混合章节。只采用与自己的 JetPack、TensorRT、Python、框架版本和报错现象相符的条目。

19.1 pip 指向错误 Conda 环境

检查:

which python
which pip
python -m pip --version
python -c "import sys; print(sys.executable)"

安装统一使用:

python -m pip install ...

19.2 WARNING: Ignoring invalid distribution -orch

说明 site-packages 中有异常 Torch 残留,例如:

-orch
~orch
~unctorch

只删除异常命名目录,不要删除正常 torch

19.3 SymPy 缺文件

报错:

No module named 'sympy.multipledispatch.core'

修复:

python -m pip uninstall -y sympy
python -m pip install --no-cache-dir --force-reinstall \
  "sympy==1.12" "mpmath==1.3.0"

注意 onnxslim 可能要求更高 SymPy。若导出使用 simplify=False,可以暂时不使用 onnxslim。

19.4 同时安装两个 OpenCV 包

错误组合:

opencv-python
opencv-contrib-python

它们共享 cv2 命名空间,一个环境只保留一种。

需要 GUI 时不要安装 headless 版本。

19.5 sudo python 找不到 cv2

ModuleNotFoundError: No module named 'cv2'

原因:sudo 使用系统 Python,不是 Conda Python。

不要用:

sudo python realtime_ctrgcn.py

只对需要权限的命令使用 sudo,例如:

sudo tegrastats
sudo nvpmodel
sudo jetson_clocks

19.6 TensorRT 与 cv2.imshow 同进程段错误

已验证现象:

TensorRT推理成功
result.plot成功
cv2.imwrite成功
cv2.imshow时Segmentation fault

解决:

  • 推理主进程不调用 HighGUI;
  • 使用独立 spawn 进程显示;
  • 正式性能测试关闭显示。

19.7 np.bool 报错

见第 7.5 节兼容补丁。

19.8 TensorRT engine 跨设备警告

Using an engine plan file across different models of devices...

重新在最终 AGX Orin 上构建 engine。

19.9 trtexec --dumpLayerInfo 段错误

先退回最小命令:

trtexec --loadEngine=model.engine --duration=10

然后逐个增加:

--profilingVerbosity=detailed
--dumpLayerInfo
--exportLayerInfo=...

如果 engine 推理正常但 layer dump 崩溃,可能是 TensorRT 8.5 工具问题,不代表 engine 本身不能运行。

19.10 --debug 后 FPS 降低

这是正常的。

调试模式会在 CUDA 阶段前后同步,以获得可信的阶段延迟。同步会破坏异步流水,因此:

--debug:用于定位阶段耗时
无 --debug:用于测最大吞吐和真实功耗

19.11 显示进程是否影响算力测试

开启显示时会增加:

  • CPU;
  • 内存复制;
  • EMC;
  • Qt/X11;
  • 桌面合成;
  • 整机功耗。

所以正式比较必须关闭:

--no-show --no-save-video

本章排错参考


20. 最终交付物和复现检查清单

分类:[通用方法]。建议所有边缘端部署项目都保留这些交付物。

20.1 模型文件

models/yolo26n-pose.pt
models/yolo26n-pose_agx-orin_jp512_trt85_fp16_640_b1.engine
models/ctrgcn_fp32_static.onnx
models/ctrgcn_fp32_static.input.npy
models/ctrgcn_fp32_static.json
models/ctrgcn_agx-orin_jp512_trt85_fp16.engine
models/posec3d_trt-5.engine

20.2 配置和权重

output_online/runs/ctrgcn/seed_42/resolved_config.py
output_online/runs/ctrgcn/seed_42/best.pth
output_online/runs/ctrgcn/seed_42/result.json
PoseC3D config
PoseC3D label map

20.3 配套脚本

export_ctrgcn_onnx.py
validate_ctrgcn_trt.py
realtime_ctrgcn_trt_fp16.py
realtime_ctrgcn_display_process.py
collect_orin_profile_generic.sh
analyze_orin_profile.py
orin_algorithm_profiled.py

20.4 正确性检查

  • YOLO .pt 可推理;
  • YOLO FP16 engine 可推理;
  • YOLO engine 关键点与 .pt 基本一致;
  • CTR-GCN ONNX checker 通过;
  • CTR-GCN FP16 engine 构建成功;
  • PyTorch/CTR-GCN TensorRT logits 一致;
  • 完整视频事件结果一致;
  • PoseC3D engine 可独立推理;
  • PoseC3D 完整链路可运行。

20.5 性能检查

  • 记录 nvpmodel
  • 两组测试都使用相同 jetson_clocks 状态;
  • 相同视频;
  • 相同 YOLO engine;
  • 相同输入分辨率;
  • 相同 warmup;
  • 相同测试时长;
  • --no-show --no-save-video
  • 分别测 engine 单体和完整链路;
  • 报告动作调用次数/100帧;
  • 报告 GR3D 平均/P95;
  • 报告 CPU 最忙核心 P95;
  • 报告 EMC;
  • 报告 VDD_IN 平均/P95/峰值;
  • 报告 FPS、P95 延迟、显存;
  • 报告准确率、召回率、误报率。

20.6 最终建议报告结构

# YOLO26-Pose + 动作识别 Orin 部署评测

## 1. 测试环境
## 2. 模型输入输出
## 3. 转换与数值一致性
## 4. 模型单体性能
## 5. 完整链路性能
## 6. 准确率与误报
## 7. CTR-GCN vs PoseC3D
## 8. FP16 vs INT8
## 9. 瓶颈分析
## 10. 最终选型结论

21. 换其他 Orin 或其他算法时如何迁移

分类:[通用迁移方法]。本章直接回答“哪些命令还能用、哪些必须重查、官方教程去哪里找”。

21.1 先判断你改变了哪一层

迁移场景分三种:

场景 A:算法不变,只换 Orin
场景 B:Orin 不变,只换算法
场景 C:Orin 和算法都换

三种场景的工作量不同:

事项场景A 换Orin场景B 换算法场景C 都换
重新采集系统信息必须建议必须
重新建立原框架精度基线建议必须必须
重新导出 ONNX建议重新验证必须必须
重新构建 TensorRT engine必须优先这样做必须必须
重写预处理/后处理通常不需要通常必须通常必须
重新做 INT8 校准更换 TRT/设备时建议重做必须必须
重新测功耗和性能必须必须必须
重新选择官方文档版本必须框架文档需重选必须

21.2 命令复用范围总表

命令或脚本其他 Orin 能否用其他算法能否用需要注意什么
uname -mlscpucat /etc/os-releaseLinux通用
cat /etc/nv_tegra_releaseJetson专用;用于选 L4T 文档
dpkg-query -W nvidia-l4t-coreJetson Debian 系统适用
collect_jetson_system_info.sh在每个目标 Conda 环境运行一次
nvpmodel -q模式编号因模块/L4T而异,不能复制编号
jetson_clocks / --show最大频率仍受 nvpmodel 约束
tegrastats字段和电源轨可能随版本/模块变化
pidstatLinux工具,需安装 sysstat
trtexec --loadEngine=...需要 TensorRT;参数以本机 --help 为准
trtexec --onnx=... --saveEngine=...ONNX必须受当前TRT支持;动态shape要另配
torch.onnx.export()是(PyTorch模型)wrapper、dummy input、opset按模型修改
onnx.checker.check_model()仅检查图合法性,不保证TensorRT支持
collect_orin_profile_generic.sh只要目标程序可作为命令运行即可
analyze_orin_profile.py通常可以如果新版 tegrastats 字段变化,需更新正则解析
YOLO model.export(format='engine')仅Ultralytics模型参数受Ultralytics/TRT版本影响
export_ctrgcn_onnx.py同CTR-GCN时可参考输入构造、wrapper和配置是CTR-GCN特定
validate_ctrgcn_trt.py同engine时可用部分可改造输入/输出名称、shape、分类语义需修改
realtime_ctrgcn_trt_fp16.py可能可用当前跟踪、事件候选和CTR-GCN完全项目化
独立显示进程方案设计思想通用;代码接入位置按程序修改

21.3 场景 A:算法不变,只换另一款 Orin

例如从 AGX Orin 换到 Orin NX 或 Orin Nano。

第一步:在新板执行系统采集

./collect_jetson_system_info.sh new_orin_system_info.txt

重点比较:

  • 板卡型号和内存容量;
  • L4T/JetPack;
  • CUDA/TensorRT;
  • Python和框架;
  • nvpmodel模式;
  • engine输入shape和精度。

第二步:不要直接假设旧 engine 可复用

TensorRT 序列化 engine 默认与构建时 TensorRT 版本和设备类型紧密相关。JetPack 上的硬件兼容模式也有限制,因此最稳妥的流程是:

保留原始 ONNX
    ↓
在新 Orin 的目标 TensorRT 环境重新构建 engine
    ↓
重新做数值一致性和性能验证

官方说明:

第三步:重新选择功耗模式

不要写死:

sudo nvpmodel -m 某个旧编号

先查看新板支持的模式:

sudo nvpmodel -q --verbose 2>/dev/null || sudo nvpmodel -q

再查目标 L4T 的 Platform Power and Performance 文档。AGX Orin、Orin NX 和 Orin Nano 的功耗范围、CPU核配置和频率上限不同。

第四步:重新跑完整性能矩阵

至少重新测:

engine 单体 trtexec
YOLO-only
完整链路
空闲基线
准确率验证
温度稳定后的持续运行

同一模型在不同 Orin 上,绝对 FPS、功耗、GPU/EMC压力都可能变化。

21.4 场景 B:Orin 不变,只换其他算法

例如:

  • YOLO-Pose 换成 RTMPose;
  • CTR-GCN 换成 ST-GCN、TCN、GRU、Transformer;
  • PoseC3D 换成 RGB 视频模型;
  • 二分类换成多分类;
  • 动作识别换成目标检测、语义分割或语音模型。

系统命令和性能采集脚本大多能继续用,但模型导出与应用接入必须重新分析。

21.4.1 先写出“模型部署契约”

对新模型填写:

框架:PyTorch / TensorFlow / Paddle / ONNX / 其他
输入数量:
输入名称:
输入shape:
动态维度:
输入dtype:
输入layout:NCHW / NHWC / NCTHW / 其他
预处理:resize / normalize / tokenize / heatmap / skeleton...
输出数量:
输出shape:
输出含义:logits / boxes / masks / keypoints / embeddings...
后处理:softmax / NMS / decode / threshold / temporal smoothing...
正确性指标:

没有这份契约,不应该开始写 TensorRT runner。

21.4.2 根据模型类型选择官方资料

新算法类型首先查什么常见部署差异
Ultralytics YOLO 检测/分割/姿态Ultralytics 对应 task + export + TensorRT可能自带预后处理;版本差异大
MMDetection/MMPose/MMAction2对应 OpenMMLab 模型 README、部署文档、MMDeploy配置驱动、custom ops、数据 pipeline
普通 PyTorch 分类/回归PyTorch ONNX + TensorRT最容易导出,但归一化和标签仍要核对
Transformer/NLP模型框架 + ONNX/TensorRT/Transformers 文档动态序列、mask、多输入、插件和显存
视频/时序模型模型仓库 + 数据 pipeline时间维、clip采样、缓存和调度影响大
自研 CUDA/插件模型TensorRT Plugin 文档必须实现、编译并随应用加载 plugin

21.4.3 通用导出框架

PyTorch 模型通常从下面的通用骨架开始,而不是复制 CTR-GCN shape:

model.eval()
with torch.no_grad():
    torch.onnx.export(
        model,
        example_inputs,       # 按新模型构造
        'model.onnx',
        input_names=[...],
        output_names=[...],
        opset_version=...,     # 按PyTorch/TRT兼容性选择
        dynamic_axes=...,      # 需要动态维度时再配置
    )

官方入口:

21.4.4 新算法必须重做正确性验证

至少比较:

原框架 FP32输出
ONNX后端输出(可用时)
TensorRT FP16输出
TensorRT INT8输出(做INT8时)

分类模型比较 logits/概率/Top-1;检测模型比较解码后的框和 mAP;分割模型比较 mask/mIoU;动作识别比较 clip级与事件级指标。

21.5 场景 C:Orin 和算法都换

不要从旧实时脚本开始改。推荐顺序:

1. 新板系统信息
2. 新算法原框架最小推理
3. 固定一组真实测试输入和期望输出
4. ONNX导出与合法性检查
5. 在新板重建FP16 engine
6. 单模型数值一致性
7. 单模型 trtexec 性能
8. 最小应用接入
9. 完整链路性能和功耗
10. INT8与调度优化

先跑最小闭环,再逐步加入摄像头、跟踪、多线程、显示、保存和业务规则。否则报错时无法判断是模型、环境还是应用调度造成的。

21.6 如何为自己的 L4T 选择正确官方文档

步骤一:查 L4T

cat /etc/nv_tegra_release

例如:

# R35 (release), REVISION: 4.1

对应文档路径通常包含:

r35.4.1

归档入口:

当前实战入口:

步骤二:查 TensorRT

python -c "import tensorrt as trt; print(trt.__version__)"
dpkg-query -W tensorrt 2>/dev/null || true

然后进入:

选择同一大版本、尽量接近的小版本。最新版文档可以用于理解新概念,但不能保证命令与旧 JetPack 兼容。

步骤三:查框架和模型版本

python -c "import torch; print(torch.__version__)"
python -c "import ultralytics; print(ultralytics.__version__)" 2>/dev/null || true
python -c "import mmaction; print(mmaction.__version__)" 2>/dev/null || true

优先选择:

  1. 当前安装版本对应的官方文档或 Git tag;
  2. 模型配置所在仓库版本;
  3. 当前模型原论文;
  4. 最后才是论坛和 issue 排错。

21.7 不同板子和算法仍然通用的性能测试原则

不论模型是什么,都应固定:

  • 同一输入数据;
  • 同一 batch 和 shape;
  • 同一精度;
  • 同一功耗模式;
  • 相同预热;
  • 相同运行时长;
  • 相同显示/保存/debug设置;
  • 相同统计口径。

并分开报告:

模型单体:trtexec或纯runner
完整链路:解码+预处理+模型+后处理+调度
产品模式:真实调用频率和业务策略

这套原则可以直接用于其他 Orin 和其他算法。

21.8 什么时候需要去看官方教程,而不是继续照抄本文

出现下面任一情况时,应暂停照抄命令并查官方资料:

  • 本机 JetPack/L4T 与 R35.4.1 不同;
  • TensorRT 不属于 8.x;
  • trtexec --help 中没有本文参数;
  • 新模型不是 Ultralytics、CTR-GCN 或 PoseC3D;
  • ONNX 出现 unsupported operator;
  • 模型有多个输入、动态序列或自定义算子;
  • 想使用 DLA、稀疏、QAT、显式 Q/DQ 或自定义 plugin;
  • engine 要跨板、跨 TensorRT 或跨操作系统;
  • tegrastats 输出字段与分析脚本不匹配;
  • 需要生产载板 bring-up、摄像头驱动、DLA或安全认证。

对应入口:

问题官方入口
JetPack版本和安装https://developer.nvidia.com/embedded/jetpack-archive
Jetson Linux、驱动、功耗、摄像头、系统工具https://docs.nvidia.com/jetson/
TensorRT版本、算子、engine、量化、pluginhttps://docs.nvidia.com/deeplearning/tensorrt/
TensorRT历史版本https://docs.nvidia.com/deeplearning/tensorrt/archives/
PyTorch ONNXhttps://docs.pytorch.org/docs/stable/onnx.html
ONNX规范和检查https://onnx.ai/onnx/
Ultralytics模型https://docs.ultralytics.com/
MMAction2https://mmaction2.readthedocs.io/
Nsight Systemshttps://docs.nvidia.com/nsight-systems/UserGuide/index.html

22. 按任务查官方资料与参考文献

22.1 版本匹配优先级

查阅资料时按以下优先级选择:

  1. 与板端版本完全一致的归档文档:本项目优先使用 JetPack 5.1.2、L4T R35.4.1、TensorRT 8.x 文档;
  2. 框架当前官方文档:用于理解概念和 API,但命令参数需检查版本差异;
  3. 模型原论文和官方代码库:用于解释模型结构、输入输出和设计原因;
  4. 论坛或 Issue:只用于排错线索,不能替代正式 API 文档和实验验证。

本机最终依据始终是:

/usr/src/tensorrt/bin/trtexec --help
python -c "import tensorrt as trt; print(trt.__version__)"
python -c "import torch; print(torch.__version__)"
python -c "import mmaction; print(mmaction.__version__)"

22.2 Jetson、JetPack、功耗和监控

22.3 YOLO26-Pose、导出与跟踪

22.4 CTR-GCN、PoseC3D 和 MMAction2

22.5 PyTorch、ONNX 和 TensorRT

22.6 FP16、INT8、PTQ 和 QAT

22.7 显示进程和 OpenCV

22.8 论文引用格式示例

在技术报告、论文或答辩材料中,可引用:

@inproceedings{chen2021ctrgcn,
  title={Channel-Wise Topology Refinement Graph Convolution for Skeleton-Based Action Recognition},
  author={Chen, Yuxin and Zhang, Ziqi and Yuan, Chunfeng and Li, Bing and Deng, Ying and Hu, Weiming},
  booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision},
  year={2021}
}

@inproceedings{duan2022posec3d,
  title={Revisiting Skeleton-based Action Recognition},
  author={Duan, Haodong and Zhao, Yue and Chen, Kai and Shao, Dian and Lin, Dahua and Dai, Bo},
  booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
  year={2022}
}

一句话总结

先识别哪些步骤属于通用方法、Jetson平台、软件版本、模型结构和当前业务;
再记录目标板系统信息,用 FP16 把模型正确部署并建立数值与性能基线;
随后用 tegrastats、pidstat、trtexec 和程序分阶段日志测 GPU、CPU、EMC、功耗、延迟和 FPS;
换板时在目标软件栈重建 engine,换算法时重做输入输出契约、预处理、后处理和正确性验证;
最后才评估 INT8 是否真的带来有价值的收益,并用真实数据重新验证准确率和阈值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值