Multistage execution
View as MarkdownSet runtime.multiStage=true to run profileset jobs in multistage stages. If you've used autoSimC or similar staged approaches, this is the same idea: run all candidates at low precision first, cull the losers, then re-sim survivors at full precision. The result is the same ranking with less total compute. Jobs without profilesets, or with multiStage omitted/false, run in a single pass as normal.
#Stages and Precision
Multistage execution runs up to three stages at default target errors of 1.0, 0.2, and 0.05. Between stages, candidates outside the statistical error band of the top performers are culled. If your profile specifies a target_error already satisfied by an earlier stage, the remaining stages are skipped. The final stage uses your profile's target_error (clamped to the platform safety floor of 0.01) when set, otherwise the stage default of 0.05.
Your profile's iterations caps the iteration count on every stage, and target_error decides when each stage stops within that cap. A high iterations does not lengthen the coarse early stages, since their higher target errors converge first. When your profile omits iterations, every stage runs under the platform safety cap (see Input Constraints).
#Directives Deferred to Final Stage
These directives are automatically held until the final stage: calculate_scale_factors, scale_delta_multiplier, center_scale_delta, dps_plot_stats, report_details, scale_only.
#Single-Run Fallback
Simmit evaluates your input before execution and may fall back to a single-run. The multiStage.reason field on the result tells you what happened:
| Reason | Meaning |
|---|---|
eligible_profileset_only | Multistage ran normally. |
disabled_by_option | runtime.multiStage was false or omitted. |
no_variants_in_input | No profileset.* directives found. Multistage requires profilesets. |
no_profileset_candidates | Profileset directives resolved to zero candidates. |
below_min_candidates | Fewer than 4 candidates. Culling is not useful at this scale. |
unsupported_copy_set_only | Input uses copy=/set= blocks without profileset.*. Not stage-separable. |
unsupported_mixed_profileset_copy_set | Input mixes profileset.* with copy=/set= blocks. Not supported for multistage. |
unsupported_multi_actor | Input declares more than one player actor. |
unsupported_stage_sensitive_directive | Input contains a directive that cannot be safely staged. |
#Reading Results
Multistage metadata lives in result.summary.multiStage:
true if multistage ran, false if the job fell back to single-pass.
The routing reason (see table above).
Array of stage objects in execution order. Empty for single-pass runs.
Each entry in multiStage.stages is:
Stage number (1-indexed).
initial, intermediate, or final.
Count entering this stage.
Count eliminated at the end of this stage. The last executed stage reports 0.
The funnel invariant stages[i].profilesets - stages[i].culled = stages[i+1].profilesets holds between adjacent stages. Multistage runs emit artifacts per stage; use kind + stage as the stable identity when consuming result.artifacts.
#Result Precision
Each profileset in result.summary.mainActor.profilesets.results carries a stage field, the highest stage it reached. That stage is also its precision: a profileset culled at an earlier stage keeps that stage's value, run at the coarser target_error for that stage (see Stages and Precision above), while a survivor was re-simmed at the final stage. The mainActor baseline is always at final-stage precision. The gap is wide: at the default stage precisions, a stage-1 mean_error is roughly 20× a final-stage one.
Because of this, two results from different stages aren't directly comparable on mean alone, an early-stage value carries its uncertainty in mean_error, which can overlap the baseline or a nearby profileset even when the means differ. Each result reports its own mean_error and mean_stddev; the full per-stage numbers are in the JSON artifacts.