|
| 1 | +# FlashSAC data-parallel CUDA graphs and wire precision |
| 2 | + |
| 3 | +## Scope and decision |
| 4 | + |
| 5 | +This change ports the measured FlashMimic multi-GPU optimization to UniLab |
| 6 | +1.5.0 (`03b75353`) with UniSim 2.1.0 (`6994cd1`). The intended PR base is `main`. |
| 7 | +The requested scope is opt-in DP graph execution and optional BF16 gradient |
| 8 | +communication; the existing runner owns process lifecycle and synchronization. |
| 9 | +No new runner or backend protocol is introduced. Defaults remain FP32 and DP |
| 10 | +eager execution. The actor/temperature fusion experiment is excluded because |
| 11 | +it did not provide a stable throughput improvement. |
| 12 | + |
| 13 | +The proposed contract is recorded in |
| 14 | +[ADR-0020](sphinx/source/adr/ADR-0020-flashsac-dp-graph-and-wire-precision.md). |
| 15 | + |
| 16 | +## Execution contract |
| 17 | + |
| 18 | +Set `+algo.algo_params.dp_whole_cycle_cuda_graph=true` to let FlashSAC capture |
| 19 | +the update cycle with NCCL reductions. The runner attaches synchronizer hooks |
| 20 | +around capture and before replay. Replacing callbacks, hooks, or checkpoint |
| 21 | +state invalidates the graph. A DP capture failure raises rather than allowing |
| 22 | +one rank to fall back to eager collectives. A loss-validity sentinel is packed |
| 23 | +with each optimizer's gradients, including losses whose derivatives are finite. |
| 24 | +On the compiled CUDA path without GradScaler, every rank therefore gates that |
| 25 | +optimizer and the critic target consistently. CPU, eager CUDA and FP16 scaler |
| 26 | +paths retain their existing finite-check behavior. |
| 27 | + |
| 28 | +This is raw CUDA graph capture around compiled objective/backward segments and |
| 29 | +optimizer updates. It is not a claim that the entire learner was compiled into |
| 30 | +one `torch.compile(fullgraph=True)` graph. |
| 31 | + |
| 32 | +`training.dp_gradient_wire_dtype=float32` preserves the default reduction. |
| 33 | +Explicit `bfloat16` packs FP32 groups of at least 1024 elements in BF16, reduces |
| 34 | +their SUM, restores gradients to FP32, then divides in FP32. Smaller groups and |
| 35 | +other source dtypes retain their original dtype. Parameters and optimizer states |
| 36 | +retain their existing dtype. Layout and precision must match across all ranks. |
| 37 | +This is a lossy numerical option, independent of AMP; long-run convergence |
| 38 | +equivalence has not been demonstrated. |
| 39 | + |
| 40 | +## Evidence and acceptance |
| 41 | + |
| 42 | +Historical experiments used UniLab `c71a7a20`, UniSim `26d17b4e`, FlashMimic |
| 43 | +`d3990125`, with env=2048, batch=2048 per rank and six updates per cycle. On the |
| 44 | +tested eight-GPU host, BF16 wire increased median throughput from 346875 to |
| 45 | +388227 steps/s (+11.9%). Relative gradient L2 error was approximately 0.3%. |
| 46 | +These are historical measurements, not benchmarks of the new upstream defaults. |
| 47 | +Learner time still grew with rank count; constant learner time was not achieved. |
| 48 | + |
| 49 | +Acceptance covers default precision, BF16 threshold and mean semantics, stable |
| 50 | +buffer storage, graph ownership and failure behavior, rank-wide nonfinite-loss |
| 51 | +gates, and Linux multi-GPU capture/replay. README commands show explicit GPU |
| 52 | +selection and user-owned MPS. CPU mock tests do not establish NCCL graph support. |
| 53 | +Full repository and current-head remote CI gates remain required before merge. |
0 commit comments