> ## Documentation Index
> Fetch the complete documentation index at: https://starforge.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a hyperparameter sweep

> Grid expansion with batch submission; the console aggregates comparisons by group

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf sweep my-grpo --profile h200:4 \
  -g policy.optimizer.kwargs.lr=1e-6,2e-6,5e-6 \
  -g grpo.kl_coef=0.01,0.05 \
  -s grpo.num_generations=8
```

`-g/--set-grid` declares a grid axis (repeatable; multiple axes take the **Cartesian product** — the example above yields 3×2=6 variants); `-s/--set` is a fixed override shared by all variants. Each variant goes through a **standard submission**: validation, quota, and queueing all apply as usual — there is no batch channel that bypasses quota.

## Preview before submitting: --dry-run

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf sweep my-grpo -g policy.optimizer.kwargs.lr=1e-6,2e-6 --dry-run
```

Only prints the variant list (the full override set for each variant) without submitting. For large grids, dry-run first to confirm before letting it go.

## Grouping and tracking

* All variants carry the same `sweep_id`; the default group name is `sweep-<experiment>-<timestamp>` (customize with `-p`);
* The console **Jobs** page badges sweep members, and the **Projects** page aggregates curves by project for comparison;
* Stop the whole group with one command:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf job stop-sweep <SWEEP_ID>     # stop all active jobs in the sweep
```

## Practical advice

<AccordionGroup>
  <Accordion title="Coarse first, then fine" icon="target">
    In the first round, sweep the learning rate across orders of magnitude (1e-6 / 1e-5 / 1e-4); once the magnitude is pinned down, do a second finer sweep within it. A blind full grid is the fastest way to burn GPUs.
  </Accordion>

  <Accordion title="Control cost with a --limit mindset" icon="coins">
    For sweep variants, first lower `max_num_steps` to the minimum that reveals a trend (e.g. 200 steps), pick the top 2, then train them at full scale.
  </Accordion>

  <Accordion title="Quota is counted per variant" icon="scale">
    6 variants × 4 GPUs = 24 GPUs of concurrent demand. Variants exceeding quota queue up rather than fail — but that also means variants in the group do not start simultaneously; watch for consistent data versions when comparing.
  </Accordion>
</AccordionGroup>

## Early stopping: cut the variants that are clearly going nowhere

Half the configurations in a grid are usually visibly hopeless within a few hundred steps. An RL run
costs tens of GPU-hours; letting them finish is burning money.

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf sweep my-grpo -g policy.lr=1e-6,1e-5,1e-4 -g grpo.kl=0.01,0.05 \
  --profile h200:4 --early-stop
```

The platform then compares variants at a few **step rungs**, stops the ones at the bottom of that
rung, and lets the rest continue to the next one:

| Flag            | Default                     | Meaning                                                                                                   |
| --------------- | --------------------------- | --------------------------------------------------------------------------------------------------------- |
| `--stop-metric` | the method's primary metric | Which metric to judge on. Direction (higher/lower is better) also comes from the method's metric contract |
| `--rungs`       | `100,300,900`               | Rungs, in steps, comma separated                                                                          |
| `--keep`        | `3`                         | Keep 1/3 at each rung. Cutting harder hurts slow-starting configurations                                  |

A stopped variant's job page states **at which step, against how many variants, and what rank** —
"stopped early" on its own explains nothing.

<Note>
  Four deliberately conservative choices:

  **Judge only at rungs**, never step by step — comparing continuously stops a variant that happens
  to be in a normal dip.

  **Compare only variants that reached the same rung** — comparing one at step 100 with one at step
  900 measures who ran longer.

  **Fewer than 4 variants at a rung means no decision** — cutting one of two is a coin flip, and the
  loss is real money.

  **At least one always survives** — no `--keep` value can empty a rung.

  Deployment-wide kill switch: `FORGE_SWEEP_EARLY_STOP_ENABLED=false` disables early stopping
  platform-wide without touching any sweep.
</Note>
