编写微基准测试#
微基准测试回答单项性能问题。资产测试使用后端专用 模拟视图 ,测量资产方法或数据属性;传感器测试使用 实际仿真场景 ,测量物理步完成后的正式传感器更新。两者都不能预测端到端环境或训练吞吐量。环境逻辑、策略推理、学习或应用启动的测量见 运行性能测试 。
参见
带类型的 Python API、格式化器和记录器内部实现,以及自定义数据生成器,见 使用性能测试 API 。
选择测试套件与后端#
从仓库根目录通过 ./isaaclab.sh 运行命令。当前 Python 环境必须已安装被测后端。PhysX 和 Newton 资产测试使用模拟视图,不依赖 Kit;PhysX 传感器测试启动 Isaac Sim;Newton 传感器测试使用已安装的 Newton 运行时,不依赖 Kit;OVPhysX 使用可选的 ovphysx 运行时 wheel,也不依赖 Kit。具有代表性的 GPU 性能数据应使用 CUDA。CPU 执行适合正确性检查或性能分析,但属于不同负载,不能混合比较 CPU 和 CUDA 结果。
要回答的问题 |
负载 |
仿真模式 |
支持的后端 |
|---|---|---|---|
单个资产方法或数据属性有多快? |
|
后端专用模拟视图,不运行物理 |
|
单个资产方法或数据属性有多快? |
|
后端专用模拟视图,不运行物理 |
|
单个资产方法或数据属性有多快? |
|
后端专用模拟视图,不运行物理 |
|
单次正式传感器更新有多快? |
|
实际场景,物理步不计时 |
|
单次正式传感器更新有多快? |
|
实际场景,物理步不计时 |
|
单次正式传感器更新有多快? |
|
实际场景,物理步不计时 |
|
单次正式传感器更新有多快? |
|
实际场景,物理步不计时 |
|
单次正式传感器更新有多快? |
|
实际场景,物理步不计时 |
|
资产入口位于各后端的 benchmark/assets 目录,传感器入口位于 benchmark/sensors 。顶层命令选择一个确切的变体和组件。比较结果时,使用相同组件、维度、模式和选择器。
运行资产测试#
资产测试单独测量 Python 输入处理、张量或索引转换、Isaac Lab 方法逻辑、后端绑定调用及数据属性计算。测试依次运行方法阶段和数据属性阶段,并分别写入沿用历史格式的方法与数据产物,使现有结果读取方式继续有效。方法覆盖受支持的状态写入、目标、力,以及材料或质量属性;数据测试覆盖后端支持的缓存属性和派生属性。
以下目录提供对应测试集:
source/isaaclab_physx/benchmark/assets/source/isaaclab_newton/benchmark/assets/source/isaaclab_ov/benchmark/assets/
测试文件 |
PhysX |
Newton |
OVPhysX |
|---|---|---|---|
|
方法与数据 |
方法与数据 |
方法与数据 |
|
方法与数据 |
方法与数据 |
方法与数据 |
|
方法与数据 |
方法与数据 |
方法与数据 |
比较后端或提交时,使用相同文件、维度和模式。
例如,运行完整的 PhysX 关节体负载:
./isaaclab.sh microbenchmark --component articulation physics=physx \
--num_instances 4096 \
--num_bodies 12 \
--num_joints 11 \
--warmup_steps 10 \
--num_iterations 1000 \
--mode all \
--backend json \
--output_dir results/physx_articulation
其他资产组件使用 rigid_object 或 rigid_object_collection 。其他后端使用以下命令:
其他资产后端命令
./isaaclab.sh microbenchmark --component articulation physics=newton_mjwarp \
--num_instances 4096 --warmup_steps 10 --num_iterations 1000
./isaaclab.sh microbenchmark --component articulation physics=newton_kamino \
--num_instances 4096 --warmup_steps 10 --num_iterations 1000
./isaaclab.sh microbenchmark --component articulation physics=ovphysx \
--num_instances 4096 --warmup_steps 10 --num_iterations 1000
运行传感器测试#
传感器测试构建实际场景,运行正式传感器。默认使用 4096 个环境、50 次预热更新和 500 次计时更新,以减少计时噪声。测试推进所选后端以生成新的源数据,但该物理步不计时。
例如,运行完整的 PhysX 接触传感器负载:
./isaaclab.sh microbenchmark --component contact_sensor physics=physx \
--num_envs 4096 --warmup_steps 50 --num_steps 500 \
--decimation 4 --history_length 0
以下接触命令使用后端专用的更新节奏控制。其他组件包括 frame_transformer 、 imu 、 pva 、 joint_wrench 和 ray_caster 。
其他传感器后端与组件命令
./isaaclab.sh microbenchmark --component contact_sensor physics=newton_mjwarp \
--num_envs 4096 --warmup_steps 50 --num_steps 500 \
--decimation 4 --history_length 0
./isaaclab.sh microbenchmark --component contact_sensor physics=ovphysx \
--num_envs 4096 --warmup_steps 50 --num_steps 500
./isaaclab.sh microbenchmark --component frame_transformer physics=newton_mjwarp \
--num_envs 4096 --num_target_frames 4 --warmup_steps 50 --num_steps 500
./isaaclab.sh microbenchmark --component imu physics=newton_kamino \
--num_envs 4096 --warmup_steps 50 --num_steps 500
./isaaclab.sh microbenchmark --component pva physics=physx \
--num_envs 4096 --warmup_steps 50 --num_steps 500
./isaaclab.sh microbenchmark --component joint_wrench physics=ovphysx \
--num_envs 4096 --warmup_steps 50 --num_steps 500 \
--benchmark_formatter summary --output_path results/sensors
./isaaclab.sh microbenchmark --component ray_caster physics=newton_mjwarp \
--num_envs 4096 --grid_size 1.0 --grid_resolution 0.25 \
--warmup_steps 50 --num_steps 500
射线投射命令默认运行平面负载,以及具有固定随机种子的确定性崎岖地形负载,分别报告 plane_sensor_update 和 rough_sensor_update 。每项负载都有对应的测量开销与验证阶段。传入 --terrain plane 或 --terrain rough ,可只运行一种负载。
修改负载#
资产参数#
参数 |
默认值 |
含义 |
|---|---|---|
|
1000 |
每个方法或属性的计时调用次数 |
|
10 |
用于编译代码和预热缓存的不计时调用次数 |
|
4096 |
模拟视图表示的资产实例数 |
|
|
方法测试要运行的输入或索引模式 |
|
|
输出格式化器: |
|
当前目录 |
带时间戳的方法与数据结果文件目录 |
|
false |
支持时,禁用方法输入形状检查 |
资产专用维度包括 --num_bodies 和 --num_joints 。默认值因文件而异,编写比较命令前先查看 --help 。
资产输入模式#
要单独测量某种选择器表示,指定其确切模式:
./isaaclab.sh microbenchmark --component articulation physics=physx \
--mode torch_tensor_int64
只由 env_ids 索引的方法支持五种选择器模式:
torch_list以 Python 列表传入环境 ID,包含列表到张量的转换,代表常见的便捷 API 用法。
torch_tensor_int32和torch_tensor_int64传入预分配的 Torch 张量,采用对应位宽的有符号索引。
warp_int32和warp_int64传入预分配的 Warp 数组,采用对应位宽的有符号索引。
具有 joint_ids 或 body_ids 的写入方法,除上述同类型模式外,还支持四种混合位宽模式:
torch_tensor_int32_int64和torch_tensor_int64_int32传入 Torch 环境选择器与元素选择器,依次使用模式名指定的位宽。
warp_int32_int64和warp_int64_int32传入 Warp 环境选择器与元素选择器,依次使用模式名指定的位宽。
受支持的 Newton 和 OVPhysX 掩码 API,使用预分配的 Warp 布尔掩码单独测试。
并非每个后端或方法都支持所有模式。只有模式在比较双方具有相同含义时,才进行比较。
关节体查找阶段#
关节体方法产物还包含实际的 find_bodies 和 find_joints 负载:
default测量原有的列表返回方式。proxy_cold在每次调用前清空资产本地选择器缓存,清空操作不计时,因此测得的查找调用包含设备本地代理选择器的创建。proxy_cached在预检时预热缓存,测量同一代理选择器的重复查找。
只有所选 GPU 空闲时,才进行计时比较。其他进程使用设备,可能主导微秒级差异。不要将仅用于正确性检查的 CPU 运行,或繁忙 GPU 上的结果,作为速度比较。
传感器参数#
参数 |
默认值 |
含义 |
|---|---|---|
|
4096 |
实际传感器实例数 |
|
500 |
计时的传感器更新或接触更新周期数 |
|
50 |
测量前不计时的仿真与传感器更新次数 |
|
|
仿真与传感器设备 |
|
|
输出格式化器: |
|
当前目录 |
带时间戳的结果文件目录 |
|
|
支持此选项的脚本会将运行标签存入元数据 |
|
required |
在 |
|
4 |
坐标系变换负载中,每个环境的目标坐标系数量 |
|
1.0 |
射线网格的宽度与长度 [m] |
|
|
选择两种射线投射地形负载,或只选择 |
|
0.25 |
射线网格间距 [m] |
传感器默认的 summary 格式化器打印终端报告并写入 JSON。添加 --output_path results/sensors ,可将产物放在仓库根目录之外。 --benchmark_formatter json 只写 JSON,不打印终端摘要; osmo 和 omniperf 选择各自的数据接收格式。适用时,PhysX 脚本还提供 --disable_graph 或 --disable_recorded_launch 。这些诊断选项用于比较正式的缓存或计算图路径与即时启动方式。测量默认正式行为时,不要启用这些禁用选项。
理解计时边界#
传感器测试采用以下计时边界:
sim.step() [untimed]
-> synchronize [exclude earlier device work]
-> start clock
-> sensor operation [record host-return time]
-> synchronize [wait for submitted device work]
-> stop clock
-> validate output [untimed]
共享工具 measure_latency() 执行两处同步,并返回主机提交时间与同步后的完成时间。首次同步将待完成的仿真、策略或无关核函数排除在传感器样本之外。运行器还单独测量相同同步边界下的空操作,以显示测量本身的开销。资产测试则在不计时的预热后,测量各方法或属性调用。
读取结果#
资产脚本以微秒打印每个方法与模式组合的均值和标准差,适用时还打印模式比较。各脚本向 --output_dir 写入带时间戳的 JSON,包含配置、硬件与软件元数据、阶段名和测量结果,完成时打印输出路径。关节体方法产物还包含上述查找阶段和原始索引核函数阶段。
传感器终端摘要示例(并非参考性能)
Results written to: results/sensors/newton_joint_wrench_sensor_2026-07-20_16-09-38.json
+------------------------------------------------------------------------------------+
| Summary Report |
+------------------------------------------------------------------------------------+
| workflow_name: newton_joint_wrench_sensor |
| num_envs: 4096 |
+------------------------------------------------------------------------------------+
| Phase: sensor_update |
| Synchronized Completion: 0.120 ms |
| Synchronized Completion p50: 0.118 ms |
| Synchronized Completion p95: 0.126 ms |
| Host Submission: 0.115 ms |
| Host Submission p50: 0.113 ms |
| Host Submission p95: 0.122 ms |
+------------------------------------------------------------------------------------+
| Phase: observer |
| Synchronized Observer Floor: 0.002 ms |
+------------------------------------------------------------------------------------+
| Phase: validation |
| Finite Wrenches: 8192 count |
| Nonzero Wrenches: 8192 count |
+------------------------------------------------------------------------------------+
JSON 测量示例(并非参考性能)
{
"name": "newton_joint_wrench_sensor sensor_update Synchronized Completion",
"mean": 0.038223,
"std": 0.00010748023074035611,
"n": 2,
"unit": "ms",
"type": "statistical"
}
生成的传感器产物为每项统计测量包含 mean 、样本 std 、 n 和 unit 。p50、p95 是同一阶段中的独立测量项。
Synchronized Completion从传感器操作开始前,到其提交的全部工作完成为止的实际延迟,是主要比较指标。
Host Submission操作返回前的主机耗时,不包含后续边界同步。它测量入队和分派成本,而非 GPU 执行时间。
Synchronized Observer Floor相同同步计时边界包围空操作的成本,用于量化测量开销,从不自动扣除。接触更新周期使用与传感器样本相同的
decimation + 1个边界。射线投射测试为每种所选地形报告对应的测量开销阶段。p50和p95单个进程内的中位数与第 95 百分位延迟,可揭示均值掩盖的抖动。进程内波动使用 JSON 的
std。Synchronized Native ReadOVPhysX 中,单独执行阻塞式后端读取的阶段。缺少该阶段表示未提供等价读取,而非读取成本为零。
Estimated Synchronized Non-read TimeOVPhysX 完整同步更新的均值减去原生读取均值。两个阶段分别采样;当数值接近时,噪声可能主导估算。这不是直接的核函数计时。
validation用于证明预期接触、数值有限的坐标变换、传感器输出、非零力旋量或射线命中的计数。输出无效时,程序报错退出,而不会生成看似有效的结果。射线投射验证按地形分别进行:平面命中与 z=0 比较,崎岖地形则报告有限的命中高度范围。
比较运行结果#
要据此说明性能:
使用相同工作站、GPU 和 CPU 状态、软件环境、设备、测试文件、维度、预热次数和计时次数。CPU 型号、频率和负载影响 Python、分派和同步开销,即使被测张量位于 GPU 上也一样。射线投射应比较相同地形阶段。
在独立、干净的进程中运行基准与候选配置。
每种配置至少重复三次,报告均值和跨运行的标准差。
检查验证输出,并保留原始 JSON 产物。
比较同一指标:不要把资产微秒耗时与传感器毫秒耗时、主机提交与同步延迟,或传感器延迟与环境 FPS 混为一谈。
启动过程单独处理。编译、场景创建、物理初始化和 CUDA 图构建不包含在报告的传感器更新延迟中,但影响命令总时长。
公开发布的 Isaac Lab 性能比较,必须在项目指定的性能测试工作站采集,并提供完整硬件和运行来源信息。本地运行适合正确性检查和排查,但不能作为官方参考数据。
重要
各后端的接触测量协议尚不完全一致。PhysX 和 Newton 测量可配置的 --decimation 个物理步周期,加上一次数据读取;OVPhysX 则测量每个物理步后的强制更新。协议未对齐时,接触结果只应用于同一后端内的性能退化检查。
添加性能测试#
添加资产测试项#
用 AssetMethodSpec 定义共享方法,用 AssetPropertySpec 定义共享数据属性。通过 AssetPropertySpec.dependencies 声明共享属性的前置依赖;只有后端需要不同依赖时,才使用适配器的 property_dependency_overrides 。后端专用的目标构建、刷新行为、能力和生成器覆盖项应保留在后端适配器中。输入应在计时调用前分配。共享 API 的等价后端行为应保持一致。不要注册后端无法有意义地实现的模式或属性。
添加传感器负载#
构建能运行正式传感器路径的最小实际场景。
采样前,预热仿真与传感器更新。
sim.step()和验证不计时。通过
measure_latency()采样,不要重复实现时钟、同步、百分位数或单位转换逻辑。通过
LatencyBenchmarkRunner输出样本,并提供匹配的同步测量开销基线。将负载维度与模式作为元数据,验证值作为测量项。
输出形状、有限值或物理信号无效时,应报错。
记录各后端专用计时阶段或协议差异。
故障排除#
导入或后端错误#
确认 ./isaaclab.sh 选择的 Python 环境已安装对应后端。OVPhysX 需要可选运行时 wheel;PhysX 传感器测试需要 Isaac Sim。
CUDA 显存不足#
资产测试减小 --num_instances ,传感器测试减小 --num_envs 。记录缩减后的规模,因为延迟随负载规模的变化规律会改变。
首次进程运行缓慢#
测量前,命令可能编译 Warp 核函数、构建场景、初始化物理或捕获 CUDA 图。预热将这些工作排除在报告的操作延迟之外,但不排除在命令总时长之外。
结果噪声较大#
确保没有其他 GPU 负载运行。增加计时迭代次数,在独立进程中重复,并报告跨运行波动。小于正常波动的差异,不能证明性能退化或改善。