编写微基准测试#

微基准测试回答单项性能问题。资产测试使用后端专用 模拟视图 ,测量资产方法或数据属性;传感器测试使用 实际仿真场景 ,测量物理步完成后的正式传感器更新。两者都不能预测端到端环境或训练吞吐量。环境逻辑、策略推理、学习或应用启动的测量见 运行性能测试 。

参见

带类型的 Python API、格式化器和记录器内部实现,以及自定义数据生成器,见 使用性能测试 API 。

选择测试套件与后端#

从仓库根目录通过 ./isaaclab.sh 运行命令。当前 Python 环境必须已安装被测后端。PhysX 和 Newton 资产测试使用模拟视图,不依赖 Kit;PhysX 传感器测试启动 Isaac Sim;Newton 传感器测试使用已安装的 Newton 运行时,不依赖 Kit;OVPhysX 使用可选的 ovphysx 运行时 wheel,也不依赖 Kit。具有代表性的 GPU 性能数据应使用 CUDA。CPU 执行适合正确性检查或性能分析,但属于不同负载,不能混合比较 CPU 和 CUDA 结果。

要回答的问题

负载

仿真模式

支持的后端

单个资产方法或数据属性有多快?

articulation

后端专用模拟视图,不运行物理

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单个资产方法或数据属性有多快?

rigid_object

后端专用模拟视图,不运行物理

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单个资产方法或数据属性有多快?

rigid_object_collection

后端专用模拟视图,不运行物理

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单次正式传感器更新有多快?

contact_sensor

实际场景,物理步不计时

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单次正式传感器更新有多快?

frame_transformer

实际场景,物理步不计时

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单次正式传感器更新有多快?

imu 或 pva

实际场景,物理步不计时

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单次正式传感器更新有多快?

joint_wrench

实际场景,物理步不计时

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

单次正式传感器更新有多快?

ray_caster

实际场景,物理步不计时

physics=physx, physics=newton_mjwarp, physics=newton_kamino, physics=ovphysx

资产入口位于各后端的 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

benchmark_articulation.py

方法与数据

方法与数据

方法与数据

benchmark_rigid_object.py

方法与数据

方法与数据

方法与数据

benchmark_rigid_object_collection.py

方法与数据

方法与数据

方法与数据

比较后端或提交时,使用相同文件、维度和模式。

例如,运行完整的 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 ,可只运行一种负载。

修改负载#

资产参数#

参数

默认值

含义

--num_iterations

1000

每个方法或属性的计时调用次数

--warmup_steps

10

用于编译代码和预热缓存的不计时调用次数

--num_instances

4096

模拟视图表示的资产实例数

--mode

all

方法测试要运行的输入或索引模式

--backend

json

输出格式化器: json 、 osmo 、 omniperf 或 summary

--output_dir

当前目录

带时间戳的方法与数据结果文件目录

--no_shape_checks

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 上的结果,作为速度比较。

传感器参数#

参数

默认值

含义

--num_envs

4096

实际传感器实例数

--num_steps

500

计时的传感器更新或接触更新周期数

--warmup_steps

50

测量前不计时的仿真与传感器更新次数

--device

cuda:0

仿真与传感器设备

--benchmark_formatter

summary

输出格式化器: summary 、 json 、 osmo 或 omniperf

--output_path

当前目录

带时间戳的结果文件目录

--label

current

支持此选项的脚本会将运行标签存入元数据

--sensor

required

在 benchmark_imu_pva.py 中选择 imu 或 pva

--num_target_frames

4

坐标系变换负载中,每个环境的目标坐标系数量

--grid_size

1.0

射线网格的宽度与长度 [m]

--terrain

all

选择两种射线投射地形负载,或只选择 plane 、 rough

--grid_resolution

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 Read

OVPhysX 中,单独执行阻塞式后端读取的阶段。缺少该阶段表示未提供等价读取,而非读取成本为零。

Estimated Synchronized Non-read Time

OVPhysX 完整同步更新的均值减去原生读取均值。两个阶段分别采样;当数值接近时,噪声可能主导估算。这不是直接的核函数计时。

validation

用于证明预期接触、数值有限的坐标变换、传感器输出、非零力旋量或射线命中的计数。输出无效时,程序报错退出,而不会生成看似有效的结果。射线投射验证按地形分别进行:平面命中与 z=0 比较,崎岖地形则报告有限的命中高度范围。

比较运行结果#

要据此说明性能:

  1. 使用相同工作站、GPU 和 CPU 状态、软件环境、设备、测试文件、维度、预热次数和计时次数。CPU 型号、频率和负载影响 Python、分派和同步开销,即使被测张量位于 GPU 上也一样。射线投射应比较相同地形阶段。

  2. 在独立、干净的进程中运行基准与候选配置。

  3. 每种配置至少重复三次,报告均值和跨运行的标准差。

  4. 检查验证输出,并保留原始 JSON 产物。

  5. 比较同一指标:不要把资产微秒耗时与传感器毫秒耗时、主机提交与同步延迟,或传感器延迟与环境 FPS 混为一谈。

  6. 启动过程单独处理。编译、场景创建、物理初始化和 CUDA 图构建不包含在报告的传感器更新延迟中,但影响命令总时长。

公开发布的 Isaac Lab 性能比较,必须在项目指定的性能测试工作站采集,并提供完整硬件和运行来源信息。本地运行适合正确性检查和排查,但不能作为官方参考数据。

重要

各后端的接触测量协议尚不完全一致。PhysX 和 Newton 测量可配置的 --decimation 个物理步周期,加上一次数据读取;OVPhysX 则测量每个物理步后的强制更新。协议未对齐时,接触结果只应用于同一后端内的性能退化检查。

添加性能测试#

添加资产测试项#

用 AssetMethodSpec 定义共享方法,用 AssetPropertySpec 定义共享数据属性。通过 AssetPropertySpec.dependencies 声明共享属性的前置依赖;只有后端需要不同依赖时,才使用适配器的 property_dependency_overrides 。后端专用的目标构建、刷新行为、能力和生成器覆盖项应保留在后端适配器中。输入应在计时调用前分配。共享 API 的等价后端行为应保持一致。不要注册后端无法有意义地实现的模式或属性。

添加传感器负载#

  1. 构建能运行正式传感器路径的最小实际场景。

  2. 采样前,预热仿真与传感器更新。

  3. sim.step() 和验证不计时。

  4. 通过 measure_latency() 采样,不要重复实现时钟、同步、百分位数或单位转换逻辑。

  5. 通过 LatencyBenchmarkRunner 输出样本,并提供匹配的同步测量开销基线。

  6. 将负载维度与模式作为元数据,验证值作为测量项。

  7. 输出形状、有限值或物理信号无效时,应报错。

  8. 记录各后端专用计时阶段或协议差异。

故障排除#

导入或后端错误#

确认 ./isaaclab.sh 选择的 Python 环境已安装对应后端。OVPhysX 需要可选运行时 wheel;PhysX 传感器测试需要 Isaac Sim。

CUDA 显存不足#

资产测试减小 --num_instances ,传感器测试减小 --num_envs 。记录缩减后的规模,因为延迟随负载规模的变化规律会改变。

首次进程运行缓慢#

测量前,命令可能编译 Warp 核函数、构建场景、初始化物理或捕获 CUDA 图。预热将这些工作排除在报告的操作延迟之外,但不排除在命令总时长之外。

结果噪声较大#

确保没有其他 GPU 负载运行。增加计时迭代次数,在独立进程中重复,并报告跨运行波动。小于正常波动的差异,不能证明性能退化或改善。