8.7 KiB
FC2 NVFP4 Scheduling Results
Status: production accepted for the canonical descriptor shape behind
H3_NVFP4_FC2_LT_SPLITK1; all other shapes retain the existing fallback.
Decision
The canonical GB10 FC2 slowdown is caused by the cuBLASLt heuristic selecting a
_stream_k kernel with poor traversal locality and heavy synchronization
polling. A documented public split-K-1 configuration is byte-exact and removes
the regression. Because this library candidate passed the complete validation
ladder, the custom persistent-kernel branch is closed.
The retained candidate is:
| Field | Value |
|---|---|
| Algorithm ID | 70 |
| Tile ID | 20 |
| Stages ID | 37 |
| Split-K | 1 |
| Reduction scheme | 0 |
| Custom option / CTA swizzle | 0 / 0 |
| Required workspace | 0 bytes |
| Supplied workspace | 64 MiB sweep; 0 bytes block/trajectory gates |
The baseline heuristic's negative split-K value is an undocumented library
sentinel. CUDA 13 has no documented public attribute that directly selects
Stream-K, so the sentinel itself is not interpreted as a public Stream-K
control. The launched baseline symbol does end in _stream_k.
Canonical Operation
- Logical GEMM:
M=37,810, N=5,376, K=14,336. - Descriptor GEMM after accepted producer padding:
M=37,824. - Inputs: packed NVFP4 E2M1 activation and weight with vector-16 UE4M3 scales.
- Accumulation/scalars: FP32; output: BF16.
- Accepted activation producer:
vortex_native_quantize_swiglu_nvfp4. - Image:
sha256:1d340e14cb6fc45ccfdbe63dde8db2a2b3aea94b493702c8a08e1f8d5b4f7b83.
Timing
The 20-round isolated sweep alternated AB/BA order in one loaded model.
| Measurement | Baseline | Split-K-1 | Result |
|---|---|---|---|
| FC2 p50 | 53.618 ms |
15.636 ms |
3.43x |
| Dense throughput p50 | 108.70 TFLOP/s |
372.74 TFLOP/s |
3.43x |
| Producer + FC2 p50 | 76.737 ms |
38.823 ms |
49.41% faster |
The negative-sentinel candidate reproduced the production-equivalent baseline
within noise. Explicit split-K factors 2, 4, 8, and 16 were rejected by
cublasLtMatmulAlgoCheck for the tested configuration space.
Complete 20-round block gates replaced only
block.mlp.fc2.forward_swiglu:
| Block | Baseline p50 | Candidate p50 | Improvement |
|---|---|---|---|
| 0 | 457.891 ms |
420.536 ms |
8.16% |
| 24 | 459.928 ms |
420.243 ms |
8.63% |
| 49 | 458.054 ms |
417.364 ms |
8.88% |
All block outputs were byte-exact against both the paired baseline and retained traversal.
| Trajectory | Baseline | Candidate | Improvement | Correctness |
|---|---|---|---|---|
| Two-step | 45.962 s |
42.516 s |
7.50% |
video/audio BF16 exact |
| Canonical 12-step | 278.201 s |
255.371 s |
8.21% |
video/audio BF16 exact |
Trajectory values are single paired runs in baseline-then-candidate
order, not repeated medians or AB/BA trials. Their approximately 38 ms per-FC2 savings agree
with the alternating isolated and complete-block gates, but the precise
end-to-end percentages retain run-order uncertainty.
The 12-step saving of 22.829 s matches approximately 600 FC2 invocations
multiplied by the isolated roughly 38 ms saving.
Production Integration
The packaged path lives in src/h3_blackwell_runtime/fc2_lt.py and is called
from Nvfp4Linear.forward_swiglu only after the accepted native producer. It
requires the FC2 role, unsharded K=14,336/N=5,376, BF16 output, no bias or
active LoRA, GB10/SM121, CUDA 13.0, cuBLAS 13.1 headers, cuBLASLt 13.0 runtime,
logical M=37,810, and packed
M=37,824. A shape-specific cublasLtMatmulAlgoCheck must pass with zero
workspace. Load, check, or execution failure falls back through the already
produced NVFP4 bytes without quantizing twice; strict mode is available through
H3_NVFP4_FC2_LT_STRICT=1. Production startup prepares the extension and
caches its measured runtime compatibility result before inference.
The 20-round production-method gate exercised Nvfp4Linear.forward_swiglu
directly and recorded 23 successful dispatches with zero fallbacks per block:
| Block | Baseline p50 | Production p50 | Improvement |
|---|---|---|---|
| 0 | 464.153 ms |
420.714 ms |
9.36% |
| 24 | 460.184 ms |
422.656 ms |
8.16% |
| 49 | 456.183 ms |
420.335 ms |
7.86% |
Production-method trajectories remained exact:
| Trajectory | Baseline | Production | Improvement | Dispatch |
|---|---|---|---|---|
| Two-step | 47.301 s |
43.728 s |
7.55% |
100/100, zero fallback |
| Canonical 12-step | 286.431 s |
262.979 s |
8.19% |
600/600, zero fallback |
The row-shape gate prevents unsafe generalization. Algorithm 70 was exact for
the tested M=37,774, 37,809, 37,810, 37,838, 37,966, and 38,222
inputs, but differed in two BF16 elements at each of M=37,711, 37,725, and
37,742 despite passing AlgoCheck. Production therefore intentionally keeps
the canonical-only guard rather than inferring exactness from nearby shapes.
The retained shape artifact records compile-time CUDA/cuBLAS versions but
predates runtime-version fields in build_info(). The final extension separately
measured CUDA runtime 13000 and cuBLASLt runtime 130000; the shape artifact
alone is not runtime-ABI evidence.
Traffic Attribution
The one-pass distinct-data footprint is:
| Category | Bytes |
|---|---|
| Activation QDATA + scales | 305,012,736 |
| Weight QDATA + scales | 43,352,064 |
| Padded BF16 output | 406,683,648 |
| Total | 755,048,448 |
Both schedules issue the same nominal operand requests:
| Requested category | Bytes | Geometric reuse |
|---|---|---|
| Weight QDATA + scales | 12,832,210,944 |
296x |
| Activation QDATA + scales | 12,832,210,944 |
about 42.1x |
| Total L2 operand reads | 25,664,424,960 |
unchanged |
The schedule does not eliminate CTA-level rereading. It changes whether those rereads remain cache-resident:
| NCU metric | Baseline _stream_k |
Split-K-1 |
|---|---|---|
| Main-kernel duration | 55.057 ms |
17.031 ms |
| Combined L2 hit rate | 53.32% |
91.10% |
| L2 read-miss bytes | 11.762 GB |
1.909 GB |
| L2 miss-byte proxy | 12.169 GB |
2.316 GB |
| Sysmem traffic proxy | 12.176 GB |
2.327 GB |
| Off-chip amplification | 16.12x |
3.07x |
| SM throughput | 25.11% |
81.79% |
| Tensor-pipe active share | 25.01% |
82.42% |
| Eligible warps/scheduler | 0.073 |
0.220 |
| Issue rate | 0.057 |
0.168 |
GB10 does not expose the usual discrete-GPU DRAM byte counters in these captures. L2 misses and the reported sysmem fill/write sectors are used as the off-chip proxy.
The 9.853 GB reduction in L2 read misses is avoided operand rereading. NCU
aggregates the two TMA input descriptors, so it cannot defensibly assign exact
miss-byte totals separately to weights and activations. The request geometry
does prove that each input family accounts for 12.832 GB of requested reads.
There is no material global partial-accumulator or output-reduction traffic:
- Candidate workspace is zero.
- Neither kernel issues global atomics or global reduction operations.
- No auxiliary reduction kernel is launched.
- Candidate writes exactly one padded BF16 output; baseline writes only
73,728bytes more. - Baseline-only local stack traffic is about
22.35 MBat L1 and almost none reaches sysmem.
The baseline's dominant scheduler stall is sleeping. Source-correlated samples
land in NANOSLEEP.SYNCS polling around synchronization phase checks. Launch
resources are otherwise the same: 12,432 CTAs, 384 threads/CTA, 168 registers
per thread, 89,088 bytes allocated shared memory, and 25% theoretical
occupancy. The gain therefore comes from traversal locality and reduced
synchronization waiting, not occupancy or a reduction workspace.
Evidence
benchmarks/gb10-fc2-nvfp4-library-sweep-20260825.jsonbenchmarks/gb10-fc2-nvfp4-block-gate-20260825.jsonbenchmarks/gb10-fc2-nvfp4-trajectory-2step-20260825.jsonbenchmarks/gb10-fc2-nvfp4-trajectory-12step-20260825.jsonbenchmarks/gb10-fc2-nvfp4-baseline-profile-20260825.jsonbenchmarks/gb10-fc2-nvfp4-splitk1-profile-20260825.jsonbenchmarks/gb10-fc2-nvfp4-baseline-20260825.csvbenchmarks/gb10-fc2-nvfp4-splitk1-20260825.csvbenchmarks/gb10-fc2-nvfp4-baseline-20260825.ncu-repbenchmarks/gb10-fc2-nvfp4-splitk1-20260825.ncu-repbenchmarks/gb10-fc2-nvfp4-production-block-gate-20260825.jsonbenchmarks/gb10-fc2-nvfp4-production-trajectory-2step-20260825.jsonbenchmarks/gb10-fc2-nvfp4-production-trajectory-12step-20260825.jsonbenchmarks/gb10-fc2-nvfp4-shape-gate-20260825.jsonsrc/h3_blackwell_runtime/csrc/fc2_nvfp4_lt.cpp
The Spark hot runtime remains stopped while performance work continues. Resident-service validation is intentionally deferred until the performance program is finished.