h3-blackwell-runtime/NVFP4_STREAMING_DESIGN.md
2026-08-25 20:30:22 +07:00

11 KiB

NVFP4 Streaming Design

Decision

Comfy Kitchen 0.2.31 cannot consume incrementally produced NVFP4 tiles. Its Python path allocates complete activation QDATA, complete swizzled block scales, and a complete BF16 output before calling cublas_gemm_blockwise_fp4 with fixed full-tensor pointers. The registered operator has no tile callback, producer interface, output stride, user output, or custom epilogue argument.

True activation-materialization removal therefore requires an owned CUTLASS or CuTe DSL mainloop. Wrapping scaled_mm_nvfp4 cannot provide it.

Available Foundation

The Spark image contains:

  • CUDA 13.0.88.
  • NVIDIA CUTLASS DSL 4.6.2.
  • CUDA Python bindings.
  • Working SM121 block-scaled E2M1/E4M3 MMA support.

The official CUTLASS 4.6 SM120/SM121 persistent cooperative block-scaled GEMM was compiled and executed on GB10 with E2M1 A/B, E4M3 scales, FP32 accumulation, and BF16 output. A 1024x1024x1024 case passed its reference check at 16.9664 us and approximately 126.57 TFLOP/s.

The public kernel still takes complete global A, B, SFA, and SFB tensors and uses separate TMA descriptors for all four. CUTLASS does not expose a ready BF16-to-NVFP4 input producer callback.

Numerical Constraint

H3's activation quantization uses:

  1. One exact global BF16 absolute maximum.
  2. One FP32 tensor scale derived from that maximum.
  3. One E4M3 block scale per 16 activation values.
  4. E2M1 values quantized using both scales.

No activation tile can be packed reference-exactly until the full activation's global reduction is complete. The minimum exact design therefore has two phases:

  1. Reduce the complete BF16 activation to one FP32 scale.
  2. Produce packed tiles and consume them in block-scaled MMA.

A future cooperative mega-kernel could combine the phases around a grid-wide barrier, but that is not the first prototype. Programmatic dependent launch can overlap independent weight preparation but cannot transfer shared-memory tiles between kernels.

Reuse Constraint

The SM121 block-scaled kernel uses cluster shape 1x1x1; there is no TMA multicast path for sharing one packed activation tile among output-N CTAs. Replacing global packed A with an ordinary per-CTA software producer would make every output-N CTA reread BF16 A and repeat scale/pack work. BF16 A is materially larger than packed E2M1 plus E4M3 scales, so this can lose despite removing the initial packed-tensor write.

The owned kernel must therefore test an N-group schedule where one CTA retains one or more packed A K-tiles while accumulating multiple output-N tiles. The number of simultaneous N tiles is constrained by accumulator registers and shared memory. This reuse factor is a first-class tuning parameter.

Prototype Sequence

P0: Owned Prepacked Baseline

Port the official persistent cooperative SM120/SM121 CuTe DSL kernel behind an experimental Vortex entry point. Match Comfy Kitchen for the four H3 projection shapes using existing packed activation and weight tensors.

Acceptance:

  • Exact BF16 output versus scaled_mm_nvfp4.
  • H3 widths 5376, 7168, and 14336 plus QKV output width 21504.
  • No regression beyond measurement noise before changing the A producer.

Current P0 result: real 128-row H3 tiles execute through the CuTe kernel. Raw block-scaled BF16 output is bit-exact for QKV, attention output, and FC1. P0 is not complete:

  • The experimental epilogue now applies H3's FP32 global-scale product before BF16 conversion. QKV, attention output, and FC1 are bit-exact.
  • FC2 at K=14336 differs even before global scaling (max_abs=8192, mean 0.015625). The correct alpha epilogue reduces final error to mean 2.42e-5, but bit equality still fails with max_abs=16. Its cuBLAS path uses a different reduction/Stream-K policy; CUTLASS K tiles 128 and 256 produce the same non-reference result.
  • The stock CuTe Float32 output mode fails the official example's own GB10 reference check and cannot be used as an accumulation oracle.

Do not begin P1 until the FC2 reduction contract is exact or FC2 is deliberately kept on the existing cuBLAS fallback. See benchmarks/gb10-cute-p0-h3-summary.json.

Decision: FC2 remains explicitly on the existing cuBLAS path. P1 and later streaming work target QKV, attention output, and FC1 only. This preserves the reference FC2 Stream-K reduction order and therefore full-model bit parity while the owned producer-consumer path is developed independently.

P1: Single-Tile Software A Producer

Replace the A and SFA TMA loads for one fixed output tile with a software warp that loads BF16 A, generates E4M3 scales and E2M1 values into the existing staged shared-memory layouts, and commits a producer-consumer pipeline stage. Keep prepacked B/SFB and the existing MMA consumer and BF16 epilogue.

Acceptance:

  • Packed bits and scale bytes agree with Comfy for every consumed tile.
  • GEMM output is bit-exact for adversarial and randomized tile inputs.
  • No global QDATA or SFA allocation in the captured kernel.

Current P1 checkpoint: the fixed 128-row producer-consumer path is exact. The existing 32-thread DMA warp loads four BF16 rows per lane, writes E2M1 and E4M3 directly into the staged sA/sSFA layouts, and lets retained B/SFB TMA completion publish each stage to the unchanged MMA consumer. The kernel takes BF16 A and one tensor scale; it does not take or allocate global activation QDATA or SFA.

Every 128-K tile has zero differing packed or scale bytes for real QKV, attention-output, and FC1 activations. Their complete 128-row GEMM outputs are also bit-exact after the alpha-before-BF16 epilogue. Exact Comfy compatibility requires PTX rcp.approx.ftz.f32, because Comfy Kitchen builds the quantizer with --use_fast_math; ordinary FP32 division changes E2M1 decisions at midpoints. CUTLASS DSL 4.6.2 also requires a static contiguous view for vector FP4 stores, as lowering the same store through a rank-2 dynamic layout aborts MLIR construction. Evidence is in benchmarks/gb10-cute-p1-stream-a-summary.json.

P1 is not deployment-complete. The next work is canonical row-count and padding support and an owned runtime module rather than validator-time patching of the CUTLASS example. FC2 continues to reject streaming and remains on Comfy/cuBLAS.

P2: N-Group Reuse

Accumulate multiple output-N tiles per produced A tile. Sweep N-group size and mainloop stages while recording registers, occupancy, achieved tensor throughput, BF16 bytes read, and total projection latency.

Reject the no-materialization design if repeated BF16 reads or reduced occupancy make it slower than the prepacked baseline. In that case, test a bounded global ring buffer of packed tiles as the producer-consumer compromise.

Current P2 result: reject the one-producer-per-output-N-CTA schedule. At 128 rows, streamed execution is 9.14x, 12.98x, and 12.44x slower than the complete scale+pack+GEMM reference for QKV, attention output, and FC1. Producer overhead scales at approximately 0.56-0.60 us per (N tile, K tile). Merely matching the removed activation quantization cost would require theoretical N reuse factors of 78, 28, and 102 respectively. Those factors are not practical through duplicate accumulator state, especially with the existing 232-register consumer requirement.

The next prototype is therefore a bounded global packed-tile ring or persistent work queue: produce each (M,K) A tile once, let all required N consumers reuse it, then recycle the slot. This deliberately restores bounded packed global traffic while avoiding complete activation materialization. See benchmarks/gb10-cute-p1-stream-a-timing-summary.json.

The bounded-ring capacity sweep is complete. A caller-owned _into CUDA producer writes exact QDATA and SFA into reusable buffers, and one full-activation scale is reused by every chunk. Capacities 128, 512, 1024, 2048, and 4096 were measured; 2048 rows is the selected point. It uses 6.19 MB for QKV/FC1 and 8.26 MB for attention output. Smaller chunks leave launch overhead, while 4096 rows regresses.

At 2048 rows, measured chunk latency improves by 10.7% for QKV, 14.4% for attention output, and 11.3% for FC1. Modeled canonical totals improve by 10.1-12.5% after charging one full-activation scale reduction. All packed bytes, scale bytes, and BF16 outputs are exact. QKV, attention output, and FC1 therefore advance to complete real-projection validation; FC2 remains on Comfy/cuBLAS. See benchmarks/gb10-cute-p2-ring-capacity-summary.json.

Complete 37,810-row projection parity now passes for QKV, attention output, and FC1 in blocks 0, 24, and 49. All 19 chunks, including the final 946-row chunk, are bit-exact with equal full checksums. QKV has a stable approximately 32 ms ring time and improves in every tested block, so it advances to opt-in resident runtime validation. Attention output timing is mixed. FC1 timing is unstable under duplicate-model unified-memory pressure, including one container stop, despite exact outputs. Do not approve those two roles from this harness. See benchmarks/gb10-cute-p2-ring-full-projection-summary.json.

The opt-in QKV-only integration passes numerical validation but fails the single-model performance gate. Alternating baseline/ring calls in one loaded block are bit-exact for blocks 0, 24, and 49, while the 2048-row schedule is 0.52-0.81% slower at block level. Capacity checks from 3072 through a full 37888-row workspace do not recover a gain; 4096 rows is closest at 0.24% slower. The reusable output also requires serialized model requests because the next projection reuses its storage after GPU work is enqueued. Keep this backend disabled. The next valid prototype must fuse chunk launches through a persistent work queue or replace the scheduler before repeating this block gate; trajectory validation is intentionally skipped. See benchmarks/gb10-cute-qkv-runtime-block-gate-summary.json.

P3: Full H3 Projection

Support canonical H3 M/N/K shapes, padding, current weight/block-scale layout, and token-row slicing. Integrate through Nvfp4Linear behind an opt-in feature flag.

P4: Exact Epilogue

After the owned GEMM is exact, add the explicit BF16 conversion, gate multiply, residual add, and final BF16 rounding sequence. Validate this independently from input streaming.

Validation Ladder

Every phase must pass, in order:

  1. Adversarial scale, E4M3, E2M1, signed-zero, midpoint, NaN, and infinity cases.
  2. Randomized packed-tile and GEMM comparisons.
  3. Real QKV, output, FC1, and FC2 projections at blocks 0, 24, and 49.
  4. Complete block equality.
  5. All 50 blocks in a denoiser step.
  6. Two-step video/audio trajectory equality.
  7. Canonical 12-step video/audio checksum equality.
  8. Full block Nsight recapture and peak-memory comparison.

No streamed path becomes a deployment default before all applicable exactness gates pass.