Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
27bbeae
feat(minimax-remover): add NVFP4 kernelized video inpainting pipeline
chenping9999 Jul 1, 2026
4b366e8
feat(minimax-remover): lazy-load runtime deps and improve build docs
chenping9999 Jul 2, 2026
274d5ec
fix(minimax-remover): share attention mode dispatch
LiangSu8899 Jul 2, 2026
c67100d
docs(minimax-remover): mention scipy extra
LiangSu8899 Jul 2, 2026
e175d76
Merge branch 'flashrt-project:main' into main
chenping9999 Jul 2, 2026
0479e40
feat(minimax-remover): add FP8 W8A8 kernelized inference pipeline
chenping9999 Jul 2, 2026
ee0f16c
docs(minimax-remover): add FP8 pipeline and update documentation for …
chenping9999 Jul 2, 2026
eba1b35
refactor(minimax-remover): unify attention dispatch and consolidate t…
chenping9999 Jul 2, 2026
b7617db
fix(minimax-remover): avoid FP8 class call patch
LiangSu8899 Jul 2, 2026
97fe4f7
feat(minimax-remover): add fp16-native fused RMS_norm VAE optimization
chenping9999 Jul 7, 2026
6f47471
feat(minimax-remover): add fused fp16 RMS_norm+SiLU kernel and standa…
chenping9999 Jul 7, 2026
b6f5b30
feat(minimax-remover): add channels-last 3D VAE pipeline for conv3d a…
chenping9999 Jul 7, 2026
01fd251
feat(minimax-remover): add FP8 implicit-GEMM conv3d kernel for VAE ac…
chenping9999 Jul 7, 2026
13517b0
feat(minimax-remover): add fused norm+silu+amax kernel and running-ma…
chenping9999 Jul 7, 2026
67da1a2
feat(minimax-remover): add fused FFN bias+gelu+quant epilogue kernel …
chenping9999 Jul 7, 2026
2a84813
feat(minimax-remover): add FP8 CUDA-graph capturable denoise path
chenping9999 Jul 8, 2026
4f08c9f
feat(minimax-remover): add fused bias+gate+residual and fp16x8 bias-a…
chenping9999 Jul 8, 2026
603692c
feat(minimax-remover): add fused adaLN+quant (shared-scale QKV) and f…
chenping9999 Jul 8, 2026
adf58d7
feat(minimax-remover): fuse norm2+quant for FFN proj0, add VAE nozero…
chenping9999 Jul 8, 2026
99ad5a3
feat(minimax-remover): add fused RMSNorm+RoPE+int8 quant kernels for Q/K
chenping9999 Jul 8, 2026
0dae91c
docs(minimax-remover): update benchmark results with serial A/B measu…
chenping9999 Jul 8, 2026
772e437
feat(minimax-remover): add purpose-built NVFP4 W4A4 VAE conv3d kernel
chenping9999 Jul 8, 2026
ed8e789
feat(minimax-remover): fuse norm+quant and Q/K bias for ~2.1% speedup
chenping9999 Jul 9, 2026
b6bcabd
fix(minimax-remover): address PR review checklist compliance
chenping9999 Jul 10, 2026
4ab5663
Merge upstream flashrt-project/FlashRT main
chenping9999 Jul 10, 2026
8ad47a8
Fix MiniMax remover optional deps and arch gate
LiangSu8899 Jul 12, 2026
f0978db
feat(minimax-remover): add training-free TeaCache step caching (3.06x…
chenping9999 Jul 13, 2026
baff23d
refactor(minimax-remover): rename --use-fp4 to --nvfp4-transformer fo…
chenping9999 Jul 13, 2026
773b13d
feat(minimax-remover): universal FP8 scale cache, PyTorch elementwise…
chenping9999 Jul 14, 2026
2fe2cdb
perf(minimax-remover): parallelize frame output with cv2, cut save ti…
chenping9999 Jul 14, 2026
01bd892
test(minimax-remover): fix smoke tests broken by universal-scale feature
chenping9999 Jul 15, 2026
15c585e
Merge upstream/main: sync INT4 (E0M3) W4A4 SM120 kernel from flashrt-…
chenping9999 Jul 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 42 additions & 14 deletions docs/minimax_remover_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ kernelized inference on Blackwell SM120. Two precision paths ship under

Both reuse the **generic** FlashRT kernels for the transformer denoise path
(quantized GEMMs, fused norm/gate/residual/gelu ops, kernel attention via
FA2 / SageAttention). The VAE encode/decode is additionally accelerated by
FA2 / SageAttention). On top of the kernelised transformer, the FP8 path
also enables **training-free TeaCache step caching** (default
`--teacache-skip 3,5,7,9`): 4 of 12 interior denoise steps reuse the cached
noise prediction instead of running the transformer — mirroring the
Motus/Cosmos3/Wan2.2 TeaCache mechanism and cutting ~0.9 s with no
measurable PSNR loss (the flow-matching velocity is highly cacheable).
The VAE encode/decode is additionally accelerated by
**model-specific fp16 fused CUDA kernels** in the standalone
`flash_rt_minimax_remover` module (opt-in build, see [Build](#build)):
`fp16_rms_norm_ncdhw` (single-pass RMSNorm, fp16-native),
Expand Down Expand Up @@ -288,7 +294,13 @@ new pipeline so the scale is re-calibrated.**
at load time; activation quantised with a calibrated static scale);
- per-block LayerNorm + adaLN modulation + gate-residual fused into Triton
kernels (fp32 statistics);
- `torch.nn.functional.scaled_dot_product_attention` -> FA2 / SageAttention.
- `torch.nn.functional.scaled_dot_product_attention` -> FA2 / SageAttention;
- **TeaCache step caching** (opt-in via `skip_steps=[...]` / quickstart
`--teacache-skip`): zeroth-order reuse of the cached noise prediction at
the listed denoise steps. On the first (calibration) call it is forwarded
to the diffusers reference loop; on steady-state calls it is forwarded to
the FP8 manual denoise (and baked into the captured CUDA Graph). Step 0
(calibration) and the last step are never skipped.

### NVFP4 — `MiniMaxRemoverPipeline` (small-region only)

Expand Down Expand Up @@ -336,8 +348,8 @@ python3 examples/minimax_remover_quickstart.py \
--masks-dir ./object_removal_data/<masks> \
--output-dir ./out # FP8 + VAE opt (default)
python3 examples/minimax_remover_quickstart.py ... --no-vae-opt # FP8, no VAE kernels
python3 examples/minimax_remover_quickstart.py ... --use-fp4 # NVFP4
python3 examples/minimax_remover_quickstart.py ... --no-flashrt # fp16 reference
python3 examples/minimax_remover_quickstart.py ... --nvfp4-transformer # NVFP4 transformer (small-region only)
python3 examples/minimax_remover_quickstart.py ... --no-flashrt # fp16 reference (disables ALL opts)
```

Wall time is a single end-to-end segment (load -> encode -> denoise loop ->
Expand All @@ -359,11 +371,12 @@ All rows compare against the non-FlashRT `--no-flashrt` fp16 reference on the
| tennis (70 frames, 432x240) | FlashRT FP8 + VAE opt + CL + FP8 conv3d + fused FFN epilogue + fused bias-gate residual | 7.57 s | 2.30x | 40.0 / 36.2 dB | 0.99981 |
| tennis (70 frames, 432x240) | **… + fused adaLN+quant (shared-scale QKV) + fused RMSNorm+RoPE + fused norm2+quant (FP8-only stack, `--no-nvfp4-vae`)** | **7.18 s** | **2.41x** | **40.0 / 36.0 dB** | 0.99981 |
| tennis (70 frames, 432x240) | **… + NVFP4 VAE (38 conv layers → W4A4, FP4 cache)** | **6.71 s** | **2.58x** | **34.7 / 30.6 dB** | 0.99981 |
| tennis (70 frames, 432x240) | **… + NVFP4 fused norm+silu+quant + FP4 cache reuse (#1) + FP8 fused norm+silu+amax+quant (#2) + Q/K bias fused into rmsnorm+rope+quant (#3, current default)** | **6.56 s** | **2.64x** | **35.2 / 31.7 dB** | 0.99918 |
| tennis (70 frames, 432x240) | FlashRT NVFP4 transformer (`--use-fp4`) | 9.52 s | 1.82x | 7.0 / 6.2 dB | 0.00000 (broken — transformer FP4 error accumulates over 12 denoise steps) |
| tennis (70 frames, 432x240) | **… + NVFP4 fused norm+silu+quant + FP4 cache reuse (#1) + FP8 fused norm+silu+amax+quant (#2) + Q/K bias fused into rmsnorm+rope+quant (#3)** | **6.56 s** | **2.64x** | **35.2 / 31.7 dB** | 0.99918 |
| tennis (70 frames, 432x240) | **… + TeaCache {3,5,7,9} step caching (current default, `--teacache-skip 3,5,7,9`)** | **5.66 s** | **3.06x** | **35.1 / 31.5 dB** | 0.99918 |
| tennis (70 frames, 432x240) | FlashRT NVFP4 transformer (`--nvfp4-transformer`) | 9.52 s | 1.82x | 7.0 / 6.2 dB | 0.00000 (broken — transformer FP4 error accumulates over 12 denoise steps) |
| bmx-trees (80 frames, 432x240) | fp16 reference (`--no-flashrt`) | 19.76 s | 1.0x | — | — |
| bmx-trees (80 frames, 432x240) | FlashRT FP8 (default) | 13.24 s | **1.49x** | 35.1 / 32.0 dB | 0.99912 |
| bmx-trees (80 frames, 432x240) | FlashRT NVFP4 transformer (`--use-fp4`) | 10.72 s | 1.84x | 7.3 / 7.0 dB | 0.00000 (broken — transformer FP4 error accumulates over 12 denoise steps) |
| bmx-trees (80 frames, 432x240) | FlashRT NVFP4 transformer (`--nvfp4-transformer`) | 10.72 s | 1.84x | 7.3 / 7.0 dB | 0.00000 (broken — transformer FP4 error accumulates over 12 denoise steps) |

> Tennis numbers are from a same-session serial A/B (`--no-flashrt
> --no-vae-opt` vs default FlashRT FP8 stack) measured on RTX 5060 Ti,
Expand All @@ -377,9 +390,15 @@ All rows compare against the non-FlashRT `--no-flashrt` fp16 reference on the
Takeaways:

- **The current default** (all of the below + NVFP4 VAE + #1/#2/#3 fused
norm+quant/bias) is **2.64× faster** than the fp16 reference (17.34 →
6.56 s) with PSNR **35.2 dB** mean over 69 inpainted frames, peak VRAM
2.57 GB (vs 3.67 GB fp16 ref, –30%). Add `--no-nvfp4-vae` and set
norm+quant/bias + **TeaCache {3,5,7,9} step caching**) is **3.06× faster**
than the fp16 reference (17.33 → 5.66 s) with PSNR **35.1 dB** mean over
69 inpainted frames, peak VRAM 2.57 GB (vs 3.67 GB fp16 ref, –30%). The
TeaCache layer (`--teacache-skip 3,5,7,9`, on by default) reuses the
cached noise prediction at 4 of 12 interior denoise steps — MiniMax-Remover's
flow-matching velocity is highly cacheable, so this contributes ~0.9 s
(6.56 → 5.66 s) with no measurable PSNR change (35.2 → 35.1 dB). Pass
`--teacache-skip ''` to disable, or `--teacache-skip 4,7` for a
conservative 2-step schedule. Add `--no-nvfp4-vae` and set
`FLASHRT_NVFP4_FUSED_NORMQUANT=0 FLASHRT_FP8_FUSED_NORMQUANT=0` for the
higher-precision FP8-only stack (~40 dB, ~7.2 s) when absolute fidelity
matters more than speed. The fused FFN epilogue kernel
Expand Down Expand Up @@ -442,12 +461,12 @@ Takeaways:
Combined steady-state 5.86 → 5.73 s; PSNR 35.16 dB mean / 31.73 worst
(vs 35.11 at the pre-fusion baseline) — the fp32 bias add in #3 is
slightly *more* precise than the fp16 bias-add it replaces.
- **NVFP4 transformer (`--use-fp4`) is unusable on full-frame latents**: cosine collapses to
- **NVFP4 transformer (`--nvfp4-transformer`) is unusable on full-frame latents**: cosine collapses to
~0.0 and PSNR to ~7 dB (median per-pixel deviation ~85/255). The FP4
quantisation error accumulates over the 12-step denoise loop in the transformer
and the output drifts to black. NVFP4 transformer is only appropriate for
small cropped regions, where its per-block error stays bounded. The NVFP4
**VAE** path (above) is unaffected because the VAE is a single-pass
**VAE** path (default, always on) is unaffected because the VAE is a single-pass
encoder/decoder with no iterative error accumulation.

### Transformer GEMM (NVFP4 vs fp16 matmul, single layer)
Expand Down Expand Up @@ -503,9 +522,10 @@ the steady state; the FP8 path calibrates on the first call then freezes.
|------|---------|--------|
| `--vae-opt` / `--no-vae-opt` | **enabled** | Install FlashRT fp16 fused VAE kernels (`fp16_rms_norm_ncdhw`, `fp16_rms_silu_ncdhw`, NDHWC variants, fused norm+silu+amax) + channels-last 3D pipeline + running-max amax sharing between norm and conv + FP8 implicit-GEMM conv3d + `WanUpsample` cast elimination. Requires the `flash_rt_minimax_remover` module. |
| `--fp8-conv` / `--no-fp8-conv` | **enabled** | Use FP8 implicit-GEMM conv3d kernel for applicable 3×3×3 causal convs (requires `--vae-opt`). Trades ~1 dB PSNR for ~14% decode speedup over channels-last-only cuDNN. |
| `--use-fp4` | off | Use NVFP4 (W4A4) transformer instead of FP8 (W8A8). Small-region only — broken on full-frame. |
| `--nvfp4-transformer` | off | Switch the **transformer** to NVFP4 (W4A4) instead of the default FP8 (W8A8). Note: the default path already uses NVFP4 for the **VAE** (single-pass, error-free); this flag adds NVFP4 to the 12-step iterative transformer denoise, where FP4 error accumulates and breaks full-frame outputs (cosine ~0.0, drifts to black). Only calibrated for small cropped regions (bbox crop). |
| `--no-nvfp4-vae` | off | Disable NVFP4 W4A4 VAE conv3d (default: enabled). Uses purpose-built NVFP4 MMA kernel for eligible VAE conv layers (Ci>=192) for ~16% VAE speedup. |
| `--no-flashrt` | off | Run the reference diffusers fp16 path (no FlashRT). |
| `--teacache-skip` | `3,5,7,9` | Training-free TeaCache step caching for the transformer denoise loop: comma-separated 0-indexed step indices to SKIP (reuse the cached noise prediction from the last computed step, matching the Motus/Cosmos3/Wan2.2 TeaCache mechanism). Step 0 (FP8 calibration) and the last step are never skipped. The default `3,5,7,9` skips 4 of 12 interior steps and is **quality-neutral** on full-frame inpainting (PSNR within noise of the no-skip path, ~225 ms saved per skipped step). Use `''` to disable, or `'4,7'` for a conservative 2-step schedule. Only applies to the FlashRT paths. |
| `--no-flashrt` | off | Master "pure reference" switch: run the vanilla diffusers fp16 path **and disable ALL FlashRT optimisations** (VAE fused kernels, FP8/NVFP4 conv, NVFP4 VAE, TeaCache). This is the ground-truth baseline for PSNR/timing A/B — no need to also pass `--no-vae-opt`. |

## Environment variables

Expand Down Expand Up @@ -545,10 +565,18 @@ output = pipeline(
num_frames=len(frames),
height=720, width=1280,
num_inference_steps=12,
skip_steps=[3, 5, 7, 9], # optional TeaCache: skip 4 interior steps (~0.9 s faster, PSNR-neutral)
)
video = output.frames
```

`skip_steps` (optional list of int) enables training-free TeaCache step
caching: the listed denoise steps reuse the cached noise prediction instead
of running the transformer, mirroring the Motus/Cosmos3/Wan2.2 mechanism.
Step 0 (FP8 calibration) and the last step are never skipped. The default
`[3, 5, 7, 9]` (also the quickstart `--teacache-skip` default) is
quality-neutral on full-frame inpainting; pass `None` or `[]` to disable.

### FP8 + NVFP4 VAE (recommended default — full-frame, fastest)

The NVFP4 VAE optimization is **enabled by default** when using the FP8
Expand Down
Loading