Skip to main content
A miles-diffusion training job is a loop over four objects. Once you understand what each one is and how data flows between them, the major flag groups are easier to place.

The four objects

The training loop

The whole of train_diffusion.py is three calls per iteration:
Every flag in miles-diffusion configures one of these four phases. train_sft.py is the train-only variant of this loop, and the SFT recipes launch it. Its rollout data does not depend on the trained weights, so it generates rollout i+1 while rollout i trains; only the first rollout is waited for. Encoders colocated with training hold their encode burst until the in-flight train step finishes, so a cold cache stalls on encoding while a warm one hides the cache load and dp split entirely. Reserving encoder GPUs with --rollout-num-gpus overlaps the encoding too.

The batch-knob invariant

In miles-diffusion a sample is a whole denoising trajectory, and the fan-out continues below it: a step strategy picks the trained timesteps, and micro-batching counts (x_t → x_{t+1}) pairs. One equation per level. Trajectory level — the four-knob invariant, resolved in miles/utils/arguments.py. rollout_batch_size is required and n_samples_per_prompt defaults to 1; of the right-hand pair, set one and the other is derived by integer division (set neither and global_batch_size defaults to dp_size; passing both with contradicting values aborts). When the left side does not divide evenly, each rollout’s samples are trimmed to a multiple of global_batch_size before training:
Pair level — what each optimizer step actually trains:
The step strategy picks trained_timesteps_per_trajectory. Each rank then trains its 1 / dp_size share, micro_batch_size pairs per forward, accumulating gradients until the optimizer step. Two independent knobs control physical batching, one per side of the loop: And one knob controls the trajectory→pair fan-out itself: --diffusion-step-strategy-path picks the SDE step subset for each engine request (the built-in sde_window or epoch_global_random_choice in miles/rollout/step_strategy_hub.py, or your own function). Training the full 10-step schedule would multiply the pair count by 10× in the example below. NFT (--loss-type nft) instead trains (x0, t) pairs at the steps --diffusion-nft-timestep-strategy-path picks per sample. Here is a full example with the numbers:

Next