简介:面向具身智能业务开发者,资源包聚焦典型模型与加速算法在CANN平台上的落地优化,内容涵盖模型剪枝、量化、混合精度训练、分布式训练与模型蒸馏等关键技术。结合硬件加速器,资源解释了如何通过模型转换、算子开发和性能调优提升推理速度与部署效率,适合正在推进智能机器人、自动驾驶、智能制造等场景模型工程化的工程师参考。压缩包共187个文件,其中以90个Python脚本和25个Shell脚本为主,用于自动化实验与部署流程;24个Markdown文档说明原理,另有patch、yaml、toml等配置辅助复现,整体仅1.2MB,便于快速下载查阅。包内同时提供多个README、开源许可证及第三方组件说明,目录结构清晰,可直接对照CANN平台的优化样例进行学习。已有40人学习使用,对希望了解具身智能中模型优化与硬件协同加速的开发者来说,这是一份轻量而实用的工程参考,能帮助降低项目初期的调研成本,并可结合具体场景改造复用其中的脚本与配置。
1. 具身智能业务里的模型加速,算的是“实时性”这笔账
具身智能业务里的模型加速,和纯互联网推理服务是两个完全不同的物种。模型侧,你要同时面对目标检测、分割、状态估计、策略网络甚至 VLA(视觉-语言-动作)大模型;算法侧,光会做 INT8 量化不够,还要知道哪些层量化不得、哪些阶段必须保留 FP16,以及控制频率为什么比单帧延迟数字更敏感。这篇文章按我实际走通一条具身智能业务链路的顺序来讲:先定模型选型,再讲加速算法,最后给一套能直接抄的落地命令和排错思路。适合刚把模型跑通、正准备往机器人身上部署的团队,也适合已经上过一轮系统、但被精度回退和时延抖动折腾过的工程师。行业标准化动作也在推进,《人形机器人与具身智能标准体系(2026版)》已经把接口和评测口径往外收,但真把模型压到 20ms 以内这件事,还得靠我们自己把每一层神经网络的账算清楚。
2. 典型模型怎么选:感知、状态估计、决策三层各有各的算力账
具身智能业务里的“模型”不是一个模型,而是一整套分层结构。我一般按感知、状态估计、决策、控制四层去拆,层与层之间的延迟预算完全不同。很多团队一开始只盯着“模型精度”,结果部署的时候发现感知用了 50ms,状态估计 10ms,决策 120ms,控制再加 5ms,一整个链条到了 185ms,抓个杯子完全跟不上手速。选型的起点不是指标刷分,而是先把每一层的延迟预算钉死。
2.1 感知层:检测与分割模型,精度和帧率在机器人上是对立的
感知层负责回答“物体在哪、是什么、什么姿态”。在这类场景里,检测和分割模型是最常用的,目标检测网络和实例分割网络基本是标配。常见选型无非是 YOLO 系、RTMDet、DETR 类,以及用于细分割的 SAM 类模型。这里有个血泪经验:在具身智能业务里,输入分辨率才是第一加速参数。
| 模型 | 输入尺寸 | 典型延迟(嵌入式 GPU) | 适合场景 |
|---|---|---|---|
| YOLOv8s | 640 | 10-20ms | 实时目标检测 |
| RTMDet-s | 640 | 15-25ms | 检测+旋转框 |
| RTMPose | 192×256 | 10-18ms | 机械臂末端/手部姿态 |
| SAM 系列 | 1024 | 60-200ms | 离线或低频语义理解 |
同样的模型,从 1280 降到 640 分辨率,推理时间直接少一半以上。但这个砍法是有边界的:如果目标在图像里只占十几个像素,你砍了分辨率,后面抓取阶段的位姿估计就会翻车。做具身智能的感知加速,我第一件事永远是拿测试集把不同分辨率下的 mAP 和检测召回率跑一遍,画一条“分辨率-精度”曲线,再结合机器人的物理极限去选。能接受 640 就不用为了刷一个点的 AP 去扛 1280 的延迟。
感知层的另一个特点是单帧模型不需要“绝对准确”,它只需要“足够及时”。所以在工程上,感知模型常常被降频运行,比如 30Hz 的相机只跑 15Hz 检测,中间用状态估计去补帧。这也是具身智能业务里一个值得尝试的常规做法:模型跑不满相机帧率,不代表业务不可用,关键是后续状态估计能不能兜住。
2.2 状态估计:滑动窗口滤波这类轻量模型,反而决定控制品质
感知层输出的是带噪声的检测框、关键点和分割掩码。这些数据如果直接喂给控制层,机器人会抖动到没法看。状态估计层负责把带噪声的观测变成平滑、可导的状态量,常见手段包括卡尔曼滤波、粒子滤波,以及工程里非常常用的滑动窗口滤波。它常常被归到“信号处理”而不是“深度学习模型”,但在具身智能业务里,它就是不折不扣的模型,而且往往是决定控制品质的那一个。
滑动窗口滤波的实现思路简单:维护一个固定长度的观测序列,对窗口内的值做加权平均或拟合。它的关键参数是窗口长度和权重分布。窗口太短,噪声压不住;窗口太长,状态量滞后严重,机械臂抓高速运动的物体时永远慢半拍。我一般会先按控制频率的 1/10 到 1/5 去估算窗口长度,比如控制频率 100Hz,窗口取 10-20 个控制周期,然后在实机上做阶跃响应测试,观察超调量和稳定时间,再微调。
如果状态量是 6DoF 位姿,直接对欧拉角做滑动窗口滤波会出问题,因为欧拉角在边界处跳变,窗口一平均就产生虚假姿态。这个坑我在项目里踩过,后来换成四元数球面线性插值(slerp)做平滑,或者直接用旋转矩阵在 SO(3) 流形上做滤波,才把问题解决。滑动窗口滤波这类轻量模型,看似没有加速需求,但它占用的 CPU 时间会影响整个实时控制回路的调度。当控制频率要求 1kHz 时,哪怕一个滤波算子多花 0.2ms,都可能让你错过控制周期,这时候同样需要做计算裁剪。
2.3 决策层:VLA 大模型和扩散策略,先问自己能不能接受几百毫秒
决策层是具身智能业务里最重的一层,也是这两年变化最快的一层。以 VLA(视觉-语言-动作)为代表的端到端大模型,直接把图像和指令映射成动作,但代价是模型规模动辄 7B 起。就算经过量化加速,单次推理也要几百毫秒。用这种模型做高频闭环控制不现实,常见做法是把 VLA 放在任务规划层面,以 1-2Hz 的频率运行,输出的是阶段性的动作意图或子目标,真正的实时动作由下层策略网络和控制层去执行。
另一类典型模型是扩散策略(Diffusion Policy)。它借鉴扩散模型的思路,通过去噪生成动作序列。推理时,模型从随机噪声出发,迭代多步去噪才能得到动作轨迹。实时性瓶颈就在这个迭代过程里——减少去噪步数是最直接的加速手段,比如从 50 步砍到 8-10 步,配合 DDIM 采样器,延迟能掉一个量级,代价是动作平滑度下降。如果动作质量接受不了,就得在模型层做蒸馏,把多步去噪蒸馏成单步或两步,这属于典型的“加速算法换精度”的取舍。
决策层还有一个工程上特别实用的概念:动作分块(Action Chunking)。策略模型不需要每个控制周期都推理,它一次推理输出未来 10-20 个控制周期的动作序列,然后控制层在这段时间里顺序执行。动作分块的长度决定了上层的推理频率,也就决定了你对模型延迟的容忍度。如果动作块是 0.2 秒,那么模型只要有 100ms 的推理延迟就够了;如果动作块只有 0.05 秒,那模型必须压到 30ms 以内。先定动作块,再定加速目标,顺序别反。
2.4 控制层:底层模型要的是 1kHz 稳定性,不是高精度推理
控制层负责把决策层的动作意图转换成关节力矩或位置指令。这一层通常不是深度学习模型,而是模型预测控制(MPC)、二次规划(QP)求解器,或者基于动力学的反馈控制器。控制器的计算量不在神经网络推理,而在优化求解。一个机械臂的全身控制(WBC)需要在 1kHz 周期内完成动力学计算和力矩分配,对计算时延的稳定性要求极其苛刻。单次求解延迟哪怕波动 2ms,都可能让力矩输出跳变,机身跟着抖动。
在控制层做加速,核心不是量化或剪枝,而是算法结构优化。常见做法包括:把非线性优化问题线性化,预先分解矩阵以减少在线计算;把实时性要求高的部分做成 C++ 实现,避免 Python 解释器开销;对多关节机器人,利用动力学算法的递归结构减少计算量。这里的模型加速,已经不在“神经网络加速算法”的范畴里,而是实打实的计算优化。但如果你把整条链路看清楚,控制层的稳定性会影响你对上层模型延迟的容忍度——控制层越稳,上层模型稍微慢一点也能兜住。
3. 加速算法的主线:量化、剪枝、蒸馏之外,还有系统级加速
模型选型定下来之后,真正的加速算法工作才开始。我做具身智能模型加速的顺序是:先量化,再剪枝/蒸馏,最后做系统级优化。这个顺序不是随便定的——量化收益最大、成本最低,通常先做;剪枝和蒸馏需要重新训练,周期长,放在后面;系统级优化是最后一道收尾,把推理引擎、内存管理、调度这些跑起来才能看到的效果榨出来。很多人上来就冲 TensorRT,结果模型本身没做轻量化,转换完延迟还是下不来。
3.1 量化:INT8 校准集必须贴近业务场景,否则精度崩在边界框
量化是具身智能模型加速里最常用的一招。常见的做法是在 PyTorch 里做训练后量化(PTQ),把权重和激活从 FP32 压到 INT8,推理速度通常能提升 2-3 倍,显存占用直接砍半。量化前后的对比,我需要一个贴近业务的校准集:必须是从实际机器人相机采回来的图,而不是训练集随机抽几张。校准集的分布一旦和业务场景偏离,精度就会崩在边界框回归上,表现为“能检测到物体但框偏了”,在抓取场景里比“检不到”更致命。
下面是一段我用 PyTorch 做感知模型 PTQ 的最小示例,核心是校准数据加载器和量化配置:
import torch from torch.ao.quantization import get_default_qconfig_mapping from torch.ao.quantization.quantize_fx import prepare_fx, convert_fx model = load_trained_model().eval() # 加载已训练好的检测模型 # 1. 准备量化配置:这里用 x86 平台的默认配置,QNNPACK 后端在部署时会替换 qconfig_mapping = get_default_qconfig_mapping("x86") prepared = prepare_fx(model, qconfig_mapping, example_inputs=torch.randn(1, 3, 640, 640)) # 2. 用贴近业务场景的图片做校准,图片量不用多,300-500 张足够 def calib_loop(): for img in load_real_scene_images(): prepared(img) calib_loop() # 3. 转换为量化模型 quantized = convert_fx(prepared) torch.save(quantized.state_dict(), "model_int8.pth")这段代码里最关键的是第二步。校准集不是越多越好,300-500 张覆盖不同光照、不同物体摆放位姿的实拍图,往往比上万张“看起来相关”的通用数据更有效。量化后一定要在验证集上对比检测框 IoU,如果低于 0.85,就要考虑对敏感层做 FP16 回退,而不是全盘 INT8。具体哪些层敏感,后面避坑章节再展开。
有两种量化路线值得在这里说清楚:PTQ 和 QAT。PTQ 快,不动训练流程,适合快速验证加速收益;QAT 精度高,但需要重新训练,工程量不小。我的建议是:先跑 PTQ 看精度差距,如果差距大,再做 QAT,不要一上来就 QAT——很多团队做完 QAT 发现瓶颈根本不在精度,而是部署环境不支持某些量化算子,白忙一场。
3.2 剪枝和蒸馏:结构化剪枝适合机器人部署,稀疏剪枝在 GPU 上收益有限
当量化已经做完,模型还是超延迟预算的时候,就要考虑模型结构层面的瘦身。剪枝的核心是去掉网络中对输出贡献小的通道或权重。在具身智能业务里,我强烈建议优先做结构化剪枝,也就是按通道或整个滤波器去剪,而不是按单个权重剪。原因是,非结构化剪枝产生的是稀疏矩阵,虽然在理论上能减少计算量,但在主流 GPU 和推理引擎上,稀疏矩阵计算效率极低,很多时候收益为零,甚至因为内存访问不连续而更慢。TensorRT 对 2:4 结构化稀疏有专门优化,但普通稀疏剪枝的模型转换过去并没有明显加速。
蒸馏则是我在决策层模型上更常用的一种加速算法:用一个大的教师模型(比如 7B VLA)蒸馏出一个小的学生模型(比如 1.5B),学生模型去拟合教师模型的输出分布,而不是直接拟合 ground truth。蒸馏的收益在 VLA 这类大模型上比剪枝更明显,因为它保住的是“行为相似”,而不是“参数结构相似”。训练的时候,学生模型拿教师模型的 soft label 做损失,再叠加一小部分真实标签损失,避免学生模型学到教师模型的错误。
剪枝和蒸馏不是互斥的,实际业务顺序通常是:先蒸馏出一个更小的学生模型,再对这个学生模型做结构化剪枝,最后做 INT8 量化。三步走完后,模型体积能压缩到原来的 10% 左右,延迟在嵌入式平台上基本能达到实时要求。每一步之后都要回到真实业务场景做验证,因为每一步都在牺牲精度,要确保每一步的精度损失在可接受范围内,别等三步全做完才发现模型已经废了。
3.3 系统级加速:算子融合、显存复用、CUDA Graph,这一层经常被忽略
模型层面的优化做完,还有一层系统级加速,这层被团队忽视的概率最高。所谓系统级加速,指的是不改变模型权重、纯粹通过优化计算图和运行时配置来降低延迟。算子融合是其中最典型的:把 Conv+BN+ReLU 三个算子合成一个算子,减少内存读写次数。PyTorch 在推理时有 torch.jit 和 torch.compile 做融合,TensorRT 在这方面更是看家本领,所以很多模型从 PyTorch 切到 TensorRT 后,什么都不改也能快 30%。
CUDA Graph 是另一个我经常用的优化手段。GPU 上每次推理,CPU 都要启动一串 kernel,这个启动开销在模型很小的时候尤其明显——一个 3ms 的模型,kernel 启动可能占 1ms。CUDA Graph 把整个推理过程捕获成一张图,之后直接回放,省掉逐 kernel 启动的开销。用 CUDA Graph 需要把模型输入固定 shape,动态 shape 会导致捕获失败,这就是为什么我前面强调固定分辨率的重要性。
还有一个容易被忽略的加速点是显存复用。模型推理时反复分配和释放显存,会产生碎片化,导致后续分配变慢。推理引擎一般会复用显存池,但不同 engine 共存时,显存池之间可能冲突。在具身智能机器人上,感知模型、决策模型、状态估计往往同时驻留,我会给每个模型划分独立的显存池上限,避免一个模型把显存吃光后触发另一个模型重新分配,这个做法在老旧的嵌入式平台上效果极其明显。
4. 把模型压到能跑:从 PyTorch 到 TensorRT/ONNX 的落地链路
所有加速算法最终都要落到具体推理引擎上。在具身智能业务里,最常用的链路是 PyTorch 训练 → ONNX 导出 → TensorRT 转换 → C++ 推理。中间每一步都有规则,不按规则走,要么转换失败,要么转换成功但性能没提升。下面按我实际部署的经验逐步讲。
4.1 模型导出:ONNX 导出时的动态轴设置与自定义算子标记
ONNX 是模型转换的中间格式,PyTorch 模型先导出成 ONNX,再转成目标平台的 engine。导出这一步踩坑最多的是动态形状和自定义算子。PyTorch 里有些算子没有 ONNX 对应实现,导出时会直接报错,或者导出成一组低效的组合算子,拖慢后续推理速度。
一个标准的导出代码片段长这样:
import torch model = load_model().eval() # 固定输入尺寸,这里用 640x640 的检测输入 dummy_input = torch.zeros(1, 3, 640, 640) torch.onnx.export( model, dummy_input, "detector.onnx", opset_version=17, # 尽量用新版 opset,老版本缺少新算子映射 input_names=["input"], output_names=["boxes", "scores"], dynamic_axes={"input": {0: "batch"}}, # 只留一个动态维度 )这里有两个要点。第一,opset_version 越高,算子映射越完整,但目标推理引擎的兼容性要先确认,TensorRT 8.x 对 opset 17 的支持已经比较成熟,更旧的版本可能只支持到 13,升级前先查文档。第二,dynamic_axes 能不开就不开,动态 shape 会让 TensorRT 的优化空间大幅缩水。如果确实需要动态 batch,只在 batch 维度上动态,高度和宽度保持固定。导出后一定要用 onnxruntime 跑一遍验证,确认输出和 PyTorch 原模型一致,再进下一步。
4.2 TensorRT 转换:trtexec 参数与 INT8 校准的落地写法
ONNX 转 TensorRT 最省事的方式是用 trtexec 命令行工具。trtexec 不只是转换工具,它本身就是最好的性能测试工具,转完直接能测延迟。下面这段命令够用:
# 转 FP16 engine,并测一下性能 trtexec --onnx=detector.onnx --saveEngine=detector_fp16.engine \ --fp16 --workspace=4096 \ --shapes=input:1x3x640x640 \ --avgRuns=100 --duration=10 # 转 INT8 engine,指定校准数据目录 trtexec --onnx=detector.onnx --saveEngine=detector_int8.engine \ --int8 --calib=./calib_data \ --shapes=input:1x3x640x640 \ --avgRuns=100关键参数说明:--fp16启用 FP16 精度,大多数检测模型精度无损;--int8启动 INT8 量化,必须配--calib指向校准数据目录,校准数据就是从实际业务场景里采集的图片,格式为二进制或图片文件;--shapes指定推理时的实际输入形状,固定形状能让 TensorRT 做更激进的显存优化,也方便建立性能基线;--avgRuns和--duration控制测试时长,我一般跑 100 次或 10 秒,数值太小时测出来的延迟波动大,不可信。
--workspace=4096给 TensorRT 指定了构图时的临时显存上限,单位是 MB,不是运行时显存。构图期间临时显存不足会导致部分优化被跳过,performance 会下降。有些模型需要在构图阶段占用大量显存,如果显存确实紧张,可以降到 2048 或 1024,但要接受一定的性能损失。转完先用--loadEngine加载测试一遍,确认能跑通,再接入业务代码。
4.3 C++ 侧的推理封装:低延迟场景为什么必须换 C++ 做装配
在具身智能业务里,模型最终的推理载体几乎都是 C++,原因主要不是因为 C++ 本身比 Python 快,而是 C++ 推理的延迟更可控。Python 里一次推理的延迟会有几十毫秒的毛刺,这些毛刺的来源包括垃圾回收、GIL 竞争和 Numpy 内存分配。控制系统的延迟分布不均,对机器人稳定性是致命的。
TensorRT 的 C++ API 核心调用只有几个步骤:创建 runtime,反序列化 engine,创建 execution context,然后绑定输入输出 buffer 并执行推理。下面是最简结构:
#include <NvInfer.h> #include <fstream> // 读取 engine 文件 std::ifstream file("detector_fp16.engine", std::ios::binary); std::vector<char> data(std::istreambuf_iterator<char>(file), {}); nvinfer1::IRuntime* runtime = nvinfer1::createInferRuntime(logger); nvinfer1::ICudaEngine* engine = runtime->deserializeEngine(data.data(), data.size()); nvinfer1::IExecutionContext* ctx = engine->createExecutionContext(); // 推理前绑定输入输出显存 buffer // input_buffer / output_buffer 在初始化阶段用 cudaMalloc 分配好 ctx->setTensorAddress("input", input_buffer); ctx->setTensorAddress("boxes", output_boxes); ctx->setTensorAddress("scores", output_scores); // 每次推理只需两步:拷贝输入 + 执行 cudaMemcpyAsync(input_buffer, h_input, bytes, cudaMemcpyHostToDevice, stream); ctx->enqueueV3(stream); // 异步执行 cudaMemcpyAsync(h_output, output_boxes, bytes, cudaMemcpyDeviceToHost, stream); cudaStreamSynchronize(stream);这个封装里有两个要点。第一,输入输出 buffer 在初始化阶段一次性分配,不要在推理循环里反复cudaMalloc,显存分配是 C++ 侧延迟抖动最重要的来源之一。第二,enqueueV3是异步调用,如果你是单模型流水线,配合 CUDA Stream 可以做到“上一帧的拷贝”和“这一帧的推理”重叠,进一步提升吞吐。等整个流程跑通后,CUDA Graph 的捕获可以放到这层再做,把enqueueV3替换成 Graph 回放。
5. 加速落地的避坑清单:5 个让机器人翻车的典型坑
这一章是血泪经验汇总。前面讲的每一条优化,在实操中都有对应的翻车姿势。我按照“现象 → 原因 → 解决”的格式写,每条都是我在具身智能业务里真实面对过的问题。
5.1 量化后抓取精度崩了:原因在分割头,不在主骨干
现象:模型 INT8 量化后,检测和分类精度掉得不多,但分割掩码边界变毛糙,机械臂抓取时定位偏了几个厘米,直接抓空。
原因:分割头和关键点回归层对激活值的分布非常敏感。主干网络的激活值分布相对集中,INT8 量化损失不大;但分割头输出的是逐像素概率,分布跨度大,量化噪声会直接体现在输出上。
解决:量化时对敏感层做 FP16 回退。TensorRT 里可以用 per-layer 精度控制,把分割头相关的卷积层标记为 FP16,其余保持 INT8。这样既能保留大部分加速收益,又能保住分割精度。另一个更长效的解法是在校准阶段加入分割头的输出 loss 反馈,但实现成本高,我一般先用层回退,效果不理想再考虑 QAT。
5.2 TensorRT 转换卡在自定义算子:先做算子替换,再考虑写插件
现象:ONNX 导出成功,但 trtexec 转换时报某个算子不支持,整个转换流程中断。
原因:PyTorch 里用了一些较新的算子或自定义 CUDA 算子,ONNX 导出时映射成了 TensorRT 不认的组合操作。
解决:优先级从高到低:第一步,改 PyTorch 实现,把特殊算子替换成标准卷积、全连接、注意力组合,大部分场景这一步就能解决;第二步,在 ONNX 图上用onnx_graphsurgeon把不支持的子图替换成等价子图;第三步,如果前两步都保不住精度或性能,再考虑针对该算子写 TensorRT Plugin。写插件是最重的方案,也是工期最容易失控的方案,我只有在算子确实无可替代时才会走这条路。
5.3 推理延迟降了,但机器人整体响应还是慢
现象:感知模型从 40ms 压到了 15ms,整个系统的端到端延迟却没有可感知的变化,机器人还是慢吞吞。
原因:延迟优化落到了“算术上”但没有落到“链路上”。端到端延迟包含相机采集、图像传输、预处理、模型推理、状态估计、控制计算、执行器响应。模型推理只占其中一段,瓶颈可能在图像传输或状态估计上。
解决:搭一个端到端延迟的测量工具,在每个环节打时间戳,先看瓶颈在哪。我在项目里吃过这个亏,花了两周优化感知模型,结果瓶颈在 USB 相机采集驱动上。正确顺序是先量化每段延迟,再集中火力优化最长的段。
5.4 低显存跑大模型:动态形状让显存反复分配,触发抖动
现象:在 8GB 显存的嵌入式设备上部署 VLA 模型,推理延迟时快时慢,平均延迟还行但 p99 夸张到几倍。
原因:动态输入形状导致 TensorRT 无法提前规划显存布局,推理时反复分配释放显存,触发碎片化和显存池重建。低显存设备上问题更极端,可用显存本来就紧。
原因:固定 batch 和输入分辨率。VLA 模型的图像输入固定尺寸,文本输入固定最大长度,超出就截断。固定形状之后 TensorRT 的显存规划最激进,p99 能显著下降。如果实在需要动态文本长度,可以给序列长度设置几档预定义值,换着用,而不是真正开放的动态范围。
5.5 滑动窗口滤波缓解了抖动,但带来了滞后
现象:滑窗滤波之后,状态量平滑了,机械臂末端不抖了,但跟踪快速运动的传送带时明显滞后,抓取成功率下降。
原因:滑动窗口滤波本质上是低通滤波,窗口越长滞后越大。控制频率高的时候,窗口长度稍微加长,滞后就会被控制环放大。
解决:把窗口长度调到最短可接受范围,我用 3-5 个控制周期起调,逐步加长,观察抓取成功率的变化。更进一步的方案是引入卡尔曼滤波,它有预测步,能补偿滞后,但调参复杂度比滑动窗口高。我的习惯是:简单的场景用短窗口滑动滤波,动态跟踪场景必须上卡尔曼,别再迷恋滑动窗口。
6. 验证加速成果:延迟预算、稳定性与端到端闭环测试
6.1 用最小脚本测端到端延迟分布
加速做完,先别急着上机,写一个脚本把延迟分布测出来。只看平均延迟是典型的新手误区,机器人控制关注的是最坏情况延迟,也就是 p95、p99。一个模型平均 20ms 但 p99 跳到 80ms,控制品质会断崖式下跌。
import time import numpy as np import onnxruntime as ort sess = ort.InferenceSession("detector_int8.onnx", providers=["CUDAExecutionProvider"]) input_data = np.random.rand(1, 3, 640, 640).astype(np.float32) latencies = [] for _ in range(200): t0 = time.perf_counter() sess.run(None, {"input": input_data}) latencies.append((time.perf_counter() - t0) * 1000) p50 = np.percentile(latencies, 50) p95 = np.percentile(latencies, 95) p99 = np.percentile(latencies, 99) print(f"p50={p50:.2f}ms p95={p95:.2f}ms p99={p99:.2f}ms")测试环境要尽量贴近实机:用机器人上实际跑的 CPU 频率、GPU 状态和内存带宽,不要用开发机测完就当结果。如果 p95 超过 p50 的 1.5 倍,说明系统里有隐性抖动,优先排查显存分配和线程调度,而不是继续往下压模型延迟。延迟分布的稳定性,比平均延迟更能反映系统是否健康。
6.2 在实机上做闭环验证
最后一步,把模型放回机器人上做闭环验证,这是终审判决。具体做法是在实机或高保真仿真环境里跑三个指标:成功完成任务的成功率、平均任务耗时、任务耗时方差。拿这三个指标和加速前的基线对比。如果成功率没有下降、任务耗时明显缩短、方差没有变大,说明加速是有效的;如果成功率略降但耗时减半,可以考虑动作分块调大一点,用上层规划来弥补下层精度的损失。
我做加速的完事标准不是“模型推理够快”,而是“闭环任务有改善”。如果加速后单帧延迟降到 10ms 但抓取成功率反而降了,那这个加速就是无效的。闭环测试跑完,记录下真实的延迟分布和成功率曲线,后面再迭代模型或换算法时,这组数据就是你做对比的基准线。我自己的习惯是每次加速迭代只改一个变量,要么改模型结构,要么改量化配置,要么改动作分块长度,避免多个变量混在一起说不清效果来源。这也是我带团队时最强调的一条。希望这篇基于实打实业务踩坑写下来的方案,能帮你在具身智能模型选型和加速算法落地的路上少走几趟弯路。
本文还有配套的精品资源,点击获取