# WP-200b — fuse unchanged dense CUDA assignment

> Engineering log · [Phase 18 — CUDA graph replay and pipeline throughput](https://borda.github.io/lucid-YOLO/engineering/phase-18-cuda-replay-throughput/)
>
> 🔗 Depends on [WP-198](https://borda.github.io/lucid-YOLO/work_packages/wp-198/), [WP-199](https://borda.github.io/lucid-YOLO/work_packages/wp-199/), [WP-200](https://borda.github.io/lucid-YOLO/work_packages/wp-200/) · Needed by none
>
> ⬅️ [WP-200](https://borda.github.io/lucid-YOLO/work_packages/wp-200/) · [Roadmap](https://borda.github.io/lucid-YOLO/ROADMAP/) · [WP-200c](https://borda.github.io/lucid-YOLO/work_packages/wp-200c/) ➡️


<a id="wp-200b"></a>

## WP-200b — retain the expressions, reduce dense intermediates

**Dense assignment remains visible after network replay.** Matched CUDA profiles on the nano oriented model attribute 80.969 ms of summed GPU work per training update to candidacy, alignment and conflict resolution. That is roughly 9.234% of complete time per update in the measured recipe, a non-overlap opportunity estimate rather than a critical-path bound. Native target construction is observed separately and is not part of the optimized-stage numerator. Actual repeated complete training decides value.

**One opt-in request, three device families and four passes.** `fused_assignment=False` is a keyword-only model and assigner option. When enabled, the route writes cross IoU directly, gathers class scores and applies the existing mask, tests rotated containment and resolves contested anchors without the large broadcast intermediates. PyTorch still supplies IoU powers and rotated sine/cosine. Top-k, the small-target and one-to-one filters, target construction/normalization, gains, epsilon and method settings stay native. Native target maxima retain their reduction order and signed-zero behavior. Conflict reduction returns the first owning index, including NaN/tie cases. Multiply-add contraction is disabled; explicit round-to-nearest PTX division preserves subnormal inputs/results. No model/optimizer arithmetic or frozen golden changes.

**Unsupported execution stays native.** The request is scoped to one assignment and restored after nesting or failure. CPU/MPS/non-NVIDIA devices, tensor subclasses, unsupported dtype/layout, compiler tracing and oversized index/grid/reduction configurations keep the original expressions. Triton 3.x on SM80 or newer is optional; importing either module without it remains safe for CPU-only tooling. A first launch failure warns once and disables that family; verified execution errors propagate. First eager launches finish before their signatures become capture-ready; unseen signatures stay native inside capture. Only compiler readiness metadata is cached, never inputs, outputs or graph pools. Recording certificates include the option, delegated helpers and kernels.

**Public workload.** DOTA-v1.0 has 104 training tiles / 2075 annotations and 13 validation tiles / 616 annotations, split by disjoint original source images 16/4. Nano OBB depth 0.5 / width 0.25 / max_channels 1024, 15 classes, 1024 px, batch 16, BF16, seed 739; four persistent workers/four Torch threads, one warmup epoch, clipping 10 and mosaic throughout (`close_mosaic=0`). L4/g2-standard-8, Torch 2.9.1+cu129, Triton 3.5.1, Lightning 2.6.6, driver 580.178.04. Both arms enable merged prepared-image caching, device HSV, epoch prefetch, network replay, orthogonalization replay and update preparation.

Five alternating 50-epoch pairs use fresh processes/contexts, prepared caches, recordings and unique empty Triton caches in both arms. Earlier excluded runs warm OS/dependency/driver caches. The complete clock begins before model/data/trainer construction and ends after synchronized fit/checkpoint completion, including cache building, recording/compilation, validation and EMA. Imports and post-fit receipt hashing are outside it and included in whole-process time.

| Measurement, median (range) | Native | Fused | Time reduction |
| -- | -- | -- | -- |
| Complete fit, seconds | 306.911 (300.181–311.299) | 273.342 (273.152–279.940) | 10.94% |
| Whole process, seconds | 312.132 (305.372–316.486) | 278.525 (278.367–285.148) | 10.77% |
| Full-batch CUDA-event step, ms | 446.689 (445.190–447.819) | 360.010 (359.133–360.173) | 19.40% |

All 350 loss byte strings per run, model/optimiser/EMA/scheduler state hashes and validation-metric byte serializations match across all ten runs. Baselines agree against themselves. Step diagnostics use identical full-batch indices after startup, excluding compile-preparation steps in either arm. Every epoch retains an active network recording; all fused arms execute the three families with none disabled. The complete/process clocks decide value; events explain the mechanism. Peak allocator statistics are recorded separately, with no OOM/capacity claim.

**Validation and limits.** Frozen-runtime VM checks pass 372 CUDA cases, excluding two exact alpha-NaN recorder failures reproduced on clean main. Torch 2.4 / Triton 3.0 passes 89 focused cases with two expected old-BF16 replay skips. CPU/doctests pass 39 cases with 48 GPU skips; 12 compiler cases retain one graph. Full pinned pre-commit passes. Public zero-score regression cases preserve native zero-weight sign bits; the missing-compiler regression covers direct module import as well as the production constructor. Real graph replay covers changed values and unaligned views. Full assignment/graph memcheck and isolated new-pass/graph initcheck pass; whole-assignment initcheck is not clean in native Torch radix top-k, reproduced by a bare dependency control. No false-positive diagnosis is made. Source/tests/extra compose with the published gradient-norm proposal and retain exact four-epoch states; that check is integration proof, not a performance claim against it.

After review, both graph tests also witness non-native results during capture, and the CUDA marker follows the backend’s SM80/compiler eligibility. The final assignment file passes 86 cases on an RTX 4060 with Torch 2.14.0+cu130/Triton 3.8.0; forcing only capture to stay native makes both graph tests fail. These are local compatibility checks. All 97 runtime files still match the five-pair VM snapshot; the strengthened assertions were not rerun on the older VM runtime lanes.

Full `make gate`, the offline 96% aggregate coverage gate, accelerator goldens and long-run/full-dataset acceptance accuracy were not run. Other tasks, devices, runtimes, smaller batches and short fits have no performance claim. Startup costs can dominate short fits; verify complete training time before enabling the option for another workload.

