Skip to content

Commit 3627310

Browse files
Standardize benchmark warm-up steps
Use step terminology across runtime and play interfaces. Record the excluded count in environment-step timing so schema and flat formatter consumers share one contract.
1 parent 8a2df0c commit 3627310

20 files changed

Lines changed: 108 additions & 54 deletions

docs/source/testing/benchmarks.rst

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ Measure environment stepping performance without any RL library:
149149
--task Isaac-Cartpole \
150150
--num_envs 4096 \
151151
--num_frames 1000 \
152-
--warmup_frames 50 \
152+
--warmup_steps 50 \
153153
--benchmark_formatter json \
154154
--output_path ./results
155155
@@ -218,7 +218,9 @@ Environment-Step Timing Semantics
218218
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219219

220220
Runtime, training, and play benchmarks report
221-
:class:`~isaaclab.benchmark.EnvironmentStepTiming`. The default
221+
:class:`~isaaclab.benchmark.EnvironmentStepTiming`. Its ``warmup_steps`` field
222+
records the exact number of initial ``env.step()`` calls excluded from
223+
timing. The default
222224
``host_return`` measurement mode records wall time until ``env.step()`` returns
223225
without forcing queued device work to complete. It describes the host-visible
224226
call boundary, not a device-complete boundary; asynchronously queued work can be
@@ -413,7 +415,7 @@ Non-RL / Runtime Benchmark Arguments
413415
* - ``--num_frames``
414416
- ``1000``
415417
- Number of environment steps to measure
416-
* - ``--warmup_frames``
418+
* - ``--warmup_steps``
417419
- ``50``
418420
- Exact number of environment steps to exclude from timing; zero measures the first step
419421
* - ``--measure_sync_step``
@@ -474,7 +476,7 @@ RL Play Arguments
474476
* - ``--num_frames``
475477
- ``100``
476478
- Number of measured inference steps
477-
* - ``--warmup_frames``
479+
* - ``--warmup_steps``
478480
- ``1``
479481
- Number of preceding environment steps to exclude from timing and throughput
480482
* - ``--checkpoint``
@@ -487,15 +489,16 @@ RL Play Arguments
487489
- ``false``
488490
- Collect the serialized synchronized diagnostic described above
489491

490-
Runtime and play execute ``warmup_frames + num_frames`` environment steps. Thus,
492+
Runtime and play execute ``warmup_steps + num_frames`` environment steps. Thus,
491493
the requested ``num_frames`` is always the exact number of measured steps. Play
492-
warmup frames are excluded only from timing and throughput; they still contribute
494+
warm-up steps are excluded only from timing and throughput; they still contribute
493495
to reward, episode-length, success-rate, and resource measurements.
494496

495-
Runtime warmup frames are excluded from steady-state timing, throughput, and
496-
synchronized environment-step measurements. When warmup is nonzero, the first
497-
warmup frame ordinary wall-clock time is retained separately as the ``first_step`` startup diagnostic.
498-
With zero warmup, the first measured frame supplies that diagnostic.
497+
Runtime warm-up steps are excluded from steady-state timing, throughput, and
498+
synchronized environment-step measurements. When warm-up is nonzero, the first
499+
warm-up step's ordinary wall-clock time is retained separately as the
500+
``first_step`` startup diagnostic. With zero warm-up, the first measured step
501+
supplies that diagnostic.
499502

500503
Measurement Types
501504
-----------------

scripts/benchmarks/test/test_benchmark_smoke.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_adapters_reject_non_positive_workloads(library: str, workflow: str, arg
6262
def test_adapters_reject_negative_warmup_steps(library: str, workflow: str, monkeypatch, capsys):
6363
"""Benchmark adapters reject negative warm-up counts."""
6464
module = _load_adapter(library, workflow)
65-
warmup_argument = "--warmup_frames" if workflow == "play" else "--warmup_steps"
65+
warmup_argument = "--warmup_steps"
6666
argv = ["--task", _TASK, warmup_argument, "-1", "--headless"]
6767
monkeypatch.setattr(sys, "argv", ["benchmark", *argv])
6868

@@ -83,7 +83,7 @@ def test_adapters_default_to_one_warmup_step(library: str, workflow: str, monkey
8383

8484
args = module._parse_args(argv)[0]
8585

86-
warmup_count = args.warmup_frames if workflow == "play" else args.warmup_steps
86+
warmup_count = args.warmup_steps
8787
assert warmup_count == 1
8888

8989

@@ -104,13 +104,13 @@ def test_adapters_accept_short_synchronized_step_flag(library: str, workflow: st
104104
def test_play_adapters_accept_warmup_larger_than_measured_workload(library: str, monkeypatch):
105105
"""Play warm-up adds calls without consuming the measured workload."""
106106
module = _load_adapter(library, "play")
107-
argv = ["--task", _TASK, "--num_frames", "2", "--warmup_frames", "3", "--headless"]
107+
argv = ["--task", _TASK, "--num_frames", "2", "--warmup_steps", "3", "--headless"]
108108
monkeypatch.setattr(sys, "argv", ["benchmark", *argv])
109109

110110
args = module._parse_args(argv)[0]
111111

112112
assert args.num_frames == 2
113-
assert args.warmup_frames == 3
113+
assert args.warmup_steps == 3
114114

115115

116116
@pytest.mark.parametrize(
@@ -179,6 +179,7 @@ def test_training_and_play_write_bundles(
179179
assert training_data["runtime"]["total_fps"]["mean"] > 0
180180
training_timing = training_data["runtime"]["environment_step_timing"]
181181
assert training_timing["environment_step_calls"] > 0
182+
assert training_timing["warmup_steps"] == 1
182183
assert training_timing["environment_step_fps"]["mean"] > 0
183184
assert training_timing["simulation_step_calls"] is None
184185
assert training_timing["simulation_step_time_s"] is None
@@ -213,6 +214,7 @@ def test_training_and_play_write_bundles(
213214
assert play_data["runtime"]["total_fps"]["mean"] > 0
214215
play_timing = play_data["runtime"]["environment_step_timing"]
215216
assert play_timing["environment_step_calls"] == 250
217+
assert play_timing["warmup_steps"] == 1
216218
assert play_timing["environment_step_fps"]["mean"] > 0
217219
assert play_timing["simulation_step_calls"] is None
218220
assert play_timing["simulation_step_time_s"] is None
@@ -244,6 +246,7 @@ def test_training_and_play_write_bundles(
244246
synchronized_play_data = _load_play_bundle(synchronized_play_output)
245247
synchronized_timing = synchronized_play_data["runtime"]["environment_step_timing"]
246248
assert synchronized_timing["environment_step_calls"] == 10
249+
assert synchronized_timing["warmup_steps"] == 1
247250
assert synchronized_timing["simulation_step_calls"] > 0
248251
assert synchronized_timing["simulation_step_time_s"]["mean"] > 0.0
249252
assert synchronized_timing["outside_simulation_step_time_s"]["mean"] >= 0.0
@@ -259,6 +262,8 @@ def test_training_and_play_write_bundles(
259262
assert play_omniperf["runtime"]["Mean Total FPS"] == pytest.approx(play_data["runtime"]["total_fps"]["mean"])
260263
assert training_omniperf["benchmark_info"]["environment_step_measurement_mode"] == "host_return"
261264
assert play_omniperf["benchmark_info"]["environment_step_measurement_mode"] == "host_return"
265+
assert training_omniperf["benchmark_info"]["environment_step_warmup_steps"] == 1
266+
assert play_omniperf["benchmark_info"]["environment_step_warmup_steps"] == 1
262267
if library == "rsl_rl":
263268
synchronized_omniperf = json.loads(next(synchronized_play_output.glob("*_omniperf.json")).read_text())
264269
assert (

scripts/benchmarks/test/test_runtime_smoke.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_runtime_writes_all_requested_formats(tmp_path, measure_sync_step: bool)
2929
"16",
3030
"--num_frames",
3131
"20",
32-
"--warmup_frames",
32+
"--warmup_steps",
3333
"0",
3434
"--seed",
3535
"0",
@@ -59,9 +59,10 @@ def test_runtime_writes_all_requested_formats(tmp_path, measure_sync_step: bool)
5959
schema_data = json.loads(schema_files[0].read_text())
6060
assert schema_data["run"]["config"]["physics_backend"] == "newton_mjwarp"
6161
assert schema_data["runtime"]["iterations_completed"] == 20
62-
assert schema_data["extra"]["warmup_frames"] == 0
62+
assert schema_data["extra"] is None
6363
assert schema_data["runtime"]["startup_time_s"]["first_step"] > 0.0
6464
timing = schema_data["runtime"]["environment_step_timing"]
65+
assert timing["warmup_steps"] == 0
6566
assert timing["environment_step_calls"] == 20
6667
assert timing["environment_step_fps"]["mean"] > 0
6768
if measure_sync_step:
@@ -79,6 +80,7 @@ def test_runtime_writes_all_requested_formats(tmp_path, measure_sync_step: bool)
7980
assert timing["environment_step_time_s"]["std"] >= 0.0
8081
omniperf_data = json.loads(omniperf_files[0].read_text())
8182
assert omniperf_data["benchmark_info"]["environment_step_measurement_mode"] == timing["measurement_mode"]
83+
assert omniperf_data["benchmark_info"]["environment_step_warmup_steps"] == 0
8284
if measure_sync_step:
8385
assert "Mean Serialized Diagnostic Total FPS" in omniperf_data["runtime"]
8486
assert "Mean Total FPS" not in omniperf_data["runtime"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Changed
2+
^^^^^^^
3+
4+
* **Breaking:** Renamed ``--warmup_frames`` to ``--warmup_steps`` for runtime
5+
and play benchmarks, and renamed ``warmup_frames`` to ``warmup_steps`` in
6+
:class:`~isaaclab.benchmark.BenchmarkRuntimeRequest` and
7+
:class:`~isaaclab.benchmark.BenchmarkPlayRequest`. Use the new step-based
8+
names when invoking or configuring benchmarks. Benchmark bundles now record
9+
the excluded count in
10+
:attr:`~isaaclab.benchmark.EnvironmentStepTiming.warmup_steps`.

source/isaaclab/isaaclab/benchmark/api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class BenchmarkRuntimeRequest:
8484
task: Registered Gym task identifier.
8585
num_envs: Number of parallel environments.
8686
num_frames: Number of measured environment steps.
87-
warmup_frames: Number of warm-up steps excluded from throughput measurements.
87+
warmup_steps: Number of warm-up steps excluded from throughput measurements.
8888
seed: Environment seed.
8989
measure_synchronized_step_breakdown: Whether to collect serialized synchronized
9090
environment/simulation step diagnostics.
@@ -97,7 +97,7 @@ class BenchmarkRuntimeRequest:
9797
task: str
9898
num_envs: int | None = None
9999
num_frames: int = 1000
100-
warmup_frames: int = 50
100+
warmup_steps: int = 50
101101
seed: int | None = None
102102
measure_synchronized_step_breakdown: bool = False
103103
presets: tuple[str, ...] = field(default_factory=tuple)
@@ -224,7 +224,7 @@ class BenchmarkPlayRequest:
224224
agent: Optional task agent configuration entry point.
225225
num_envs: Number of parallel environments.
226226
num_frames: Number of measured inference steps.
227-
warmup_frames: Number of initial environment steps excluded from environment-step timing.
227+
warmup_steps: Number of initial environment steps excluded from environment-step timing.
228228
seed: Environment seed.
229229
measure_synchronized_step_breakdown: Whether to collect serialized synchronized
230230
environment/simulation step diagnostics.
@@ -241,7 +241,7 @@ class BenchmarkPlayRequest:
241241
agent: str | None = None
242242
num_envs: int | None = None
243243
num_frames: int = 100
244-
warmup_frames: int = 1
244+
warmup_steps: int = 1
245245
seed: int | None = None
246246
measure_synchronized_step_breakdown: bool = False
247247
presets: tuple[str, ...] = field(default_factory=tuple)

source/isaaclab/isaaclab/benchmark/builders.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def build_runtime(
132132
steps_per_iteration: int,
133133
aggregate_throughput: bool = False,
134134
frames_per_environment_step: int | None = None,
135+
environment_step_warmup_steps: int = 0,
135136
environment_step_times_s: Sequence[float] | None = None,
136137
simulation_step_times_s: Sequence[float] | None = None,
137138
simulation_step_calls: int | None = None,
@@ -150,6 +151,7 @@ def build_runtime(
150151
remains the ordinary sample deviation of the per-iteration rates,
151152
and peak remains the maximum per-iteration throughput.
152153
frames_per_environment_step: Number of environment frames processed by each vectorized ``env.step()`` call.
154+
environment_step_warmup_steps: Number of initial environment-step calls excluded from timing.
153155
environment_step_times_s: Positive per-environment-step wall times [s].
154156
simulation_step_times_s: Synchronized simulation wall times per environment step [s].
155157
simulation_step_calls: Number of measured simulation-step calls.
@@ -230,6 +232,7 @@ def build_runtime(
230232
environment_step_calls=len(environment_samples),
231233
simulation_step_calls=simulation_step_calls,
232234
measurement_mode=("serialized_synchronized" if simulation_step_times_s is not None else "host_return"),
235+
warmup_steps=environment_step_warmup_steps,
233236
)
234237

235238
return Runtime(

source/isaaclab/isaaclab/benchmark/dispatch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def _request_argv(request: BenchmarkRequest) -> list[str]:
130130

131131
if request.workflow == "runtime":
132132
_append_value(argv, "--num_frames", request.num_frames)
133-
_append_value(argv, "--warmup_frames", request.warmup_frames)
133+
_append_value(argv, "--warmup_steps", request.warmup_steps)
134134
elif request.workflow == "startup":
135135
_append_value(argv, "--top_n", request.top_n)
136136
_append_value(argv, "--whitelist_config", request.whitelist_config)
@@ -163,7 +163,7 @@ def _request_argv(request: BenchmarkRequest) -> list[str]:
163163
_append_value(argv, "--checkpoint", request.checkpoint)
164164
_append_value(argv, "--agent", request.agent)
165165
_append_value(argv, "--num_frames", request.num_frames)
166-
_append_value(argv, "--warmup_frames", request.warmup_frames)
166+
_append_value(argv, "--warmup_steps", request.warmup_steps)
167167

168168
if getattr(request, "measure_synchronized_step_breakdown", False):
169169
argv.append("--measure_sync_step")

source/isaaclab/isaaclab/benchmark/entrypoints/backends/rl_games/benchmark_play_rl_games.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def _parse_args(argv: list[str]):
6666
help="Measure a serialized synchronized simulation and outside-simulation step breakdown.",
6767
)
6868
parser.add_argument(
69-
"--warmup_frames",
69+
"--warmup_steps",
7070
type=parse_non_negative_int,
7171
default=1,
7272
help="Exclude the first N env.step() calls from environment-step timing. Default 1 removes cold start.",
@@ -175,7 +175,7 @@ def run(argv: list[str]) -> BenchmarkResult:
175175
"name": "environment_step_measurement_mode",
176176
"data": ("serialized_synchronized" if args_cli.measure_sync_step else "host_return"),
177177
},
178-
{"name": "environment_step_warmup_frames", "data": args_cli.warmup_frames},
178+
{"name": "environment_step_warmup_steps", "data": args_cli.warmup_steps},
179179
{"name": "presets", "data": ",".join(cfg.presets)},
180180
]
181181
},
@@ -243,14 +243,14 @@ def policy(obs):
243243
environment_step_timer = stepping.EnvironmentStepTimingRecorder(
244244
env,
245245
measure_synchronized_step_breakdown=args_cli.measure_sync_step,
246-
warmup_steps=args_cli.warmup_frames,
246+
warmup_steps=args_cli.warmup_steps,
247247
)
248-
total_frames = args_cli.warmup_frames + args_cli.num_frames
248+
total_frames = args_cli.warmup_steps + args_cli.num_frames
249249
with environment_step_timer, BenchmarkMonitor(benchmark, interval=1.0):
250250
all_step_times, reward, ep_length, success_rate = stepping.run_play_loop(env, policy, total_frames)
251251

252252
first_step_s = all_step_times[0]
253-
step_times = all_step_times[args_cli.warmup_frames :]
253+
step_times = all_step_times[args_cli.warmup_steps :]
254254

255255
benchmark.update_manual_recorders()
256256

@@ -268,6 +268,7 @@ def policy(obs):
268268
total_fps=fps,
269269
steps_per_iteration=num_envs,
270270
frames_per_environment_step=env.unwrapped.num_envs,
271+
environment_step_warmup_steps=args_cli.warmup_steps,
271272
environment_step_times_s=environment_step_timer.step_times_s,
272273
simulation_step_times_s=environment_step_timer.simulation_step_times_s,
273274
simulation_step_calls=environment_step_timer.simulation_step_calls,

source/isaaclab/isaaclab/benchmark/entrypoints/backends/rl_games/benchmark_train_rl_games.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def run(argv: list[str]) -> BenchmarkResult:
306306
total_fps=total_fps_series,
307307
steps_per_iteration=steps_per_iteration,
308308
frames_per_environment_step=env.unwrapped.num_envs,
309+
environment_step_warmup_steps=args_cli.warmup_steps,
309310
environment_step_times_s=environment_step_timer.step_times_s,
310311
simulation_step_times_s=environment_step_timer.simulation_step_times_s,
311312
simulation_step_calls=environment_step_timer.simulation_step_calls,

source/isaaclab/isaaclab/benchmark/entrypoints/backends/rsl_rl/benchmark_play_rsl_rl.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def _parse_args(argv: list[str]) -> tuple[argparse.Namespace, list[str]]:
6767
help="Measure a serialized synchronized simulation and outside-simulation step breakdown.",
6868
)
6969
parser.add_argument(
70-
"--warmup_frames",
70+
"--warmup_steps",
7171
type=parse_non_negative_int,
7272
default=1,
7373
help="Exclude the first N env.step() calls from environment-step timing. Default 1 removes cold start.",
@@ -172,7 +172,7 @@ def run(argv: list[str]) -> BenchmarkResult:
172172
"name": "environment_step_measurement_mode",
173173
"data": ("serialized_synchronized" if args.measure_sync_step else "host_return"),
174174
},
175-
{"name": "environment_step_warmup_frames", "data": args.warmup_frames},
175+
{"name": "environment_step_warmup_steps", "data": args.warmup_steps},
176176
{"name": "presets", "data": ",".join(cfg.presets)},
177177
]
178178
},
@@ -200,14 +200,14 @@ def run(argv: list[str]) -> BenchmarkResult:
200200
environment_step_timer = stepping.EnvironmentStepTimingRecorder(
201201
env,
202202
measure_synchronized_step_breakdown=args.measure_sync_step,
203-
warmup_steps=args.warmup_frames,
203+
warmup_steps=args.warmup_steps,
204204
)
205-
total_frames = args.warmup_frames + args.num_frames
205+
total_frames = args.warmup_steps + args.num_frames
206206
with environment_step_timer, BenchmarkMonitor(benchmark, interval=1.0):
207207
all_step_times, reward, ep_length, success_rate = stepping.run_play_loop(env, policy, total_frames)
208208

209209
first_step_s = all_step_times[0]
210-
step_times = all_step_times[args.warmup_frames :]
210+
step_times = all_step_times[args.warmup_steps :]
211211

212212
benchmark.update_manual_recorders()
213213

@@ -225,6 +225,7 @@ def run(argv: list[str]) -> BenchmarkResult:
225225
total_fps=fps,
226226
steps_per_iteration=num_envs,
227227
frames_per_environment_step=env.unwrapped.num_envs,
228+
environment_step_warmup_steps=args.warmup_steps,
228229
environment_step_times_s=environment_step_timer.step_times_s,
229230
simulation_step_times_s=environment_step_timer.simulation_step_times_s,
230231
simulation_step_calls=environment_step_timer.simulation_step_calls,

0 commit comments

Comments
 (0)