unsloth/tests
danielhanchen cc4832b605 flex/moe: compile_walker option — 2x decode throughput on Qwen3 MoE
Optional ``FlexMoEInference(compile_walker=True)`` / env var
``UNSLOTH_FLEX_COMPILE_WALKER=1`` wraps the decode walker
(``call_moe_model_with_flex_kwargs``) with
``torch.compile(fullgraph=False, dynamic=False)`` before the CUDA
graph capture kicks in. Inductor fuses the layernorm + residual +
router pointwise ops, and the compiled kernels end up recorded
inside the captured graph. Net: ~2x decode tok/s on the grouped_mm
path with no change in VRAM, no correctness regression, and no
user-facing API change unless the flag is set.

Numbers on Qwen3-30B-A3B-Instruct-2507, B200, 128 new tokens,
bs sweep, median of 2 timed rounds after 1 warmup:

| precision | bs | baseline (v2) | + compile_walker | speedup |
|-----------|---:|--------------:|-----------------:|--------:|
| 4bit      | 16 |           699 |           1347.8 |   1.93x |
| 4bit      | 32 |          1243 |           2423.9 |   1.95x |
| 4bit      | 48 |          1735 |         3383.2   |   1.95x |
| 4bit      | 64 |          1523 |           2981.9 |   1.96x |
| bf16      | 16 |             — |           1401.1 |       — |
| bf16      | 32 |             — |           2864.0 |       — |
| bf16      | 48 |             — |       **3911.1** |       — |

Peak throughput: 3911 tok/s at bf16 bs=48 — 39x the pure-HF naive
baseline on the same workload (101.1 tok/s with
``AutoModelForCausalLM`` + eager attn, left-padded, no unsloth).
At 4bit bs=48, 51x the pure-HF naive baseline (66.7 tok/s).

GRPO 5-step validation (Qwen3_MoE_GRPO.py --backend flex
--max_steps 5 on DAPO-Math-17k):

| precision | baseline (v2) | + compile_walker | speedup |
|-----------|--------------:|-----------------:|--------:|
| 4bit      |        548.3s |           434.5s |   1.26x |
| bf16      |        451.8s |       **407.4s** |   1.10x |

Peak VRAM unchanged (130-133 GB). Loss / KL stable on both, no
NaN, rewards pegged at -7.5 (base-model artifact; orthogonal).

Parity (greedy 32 tokens × 3 prompts at bf16 and 4bit via
``FLEX_MOE_COMPILE_WALKER=1 tests/flex_moe_parity.py``):
flex-captured with the compile wrap matches flex-captured without
the compile wrap on 6/6 prompts with no gibberish, and matches pure
``transformers.AutoModelForCausalLM`` 32/32 on 5 of 6 (prompt ×
precision) pairs (the one divergence is a tie-break logit boundary
on an open-ended continuation — both coherent English).

Bisection of a few torch.compile flag sets against the default at
bs=32 4bit (max_batch_size=32):

| config                                                     |  tok/s |
|------------------------------------------------------------|-------:|
| default (``torch.compile(fullgraph=False, dynamic=False)``)| 1581.5 |
| + max_autotune + coord_descent + aggressive_fusion         | 1704.9 |
| + ``freezing=True``                                        |  935.7 |

``freezing=True`` is a regression on this path; shipping with the
default config only. The other flags are +7.8% at this size but
at large bs (48+) the max_autotune variant timed out during
compile (>40 min) so the default stays the ship-target for now.

Other attention backends don't help on B200 today:
- pure HF with ``attn_implementation="sdpa"``: cuDNN Frontend error
  ("No valid execution plans built") on sm_100 + torch 2.11.
- ``flash_attention_2`` 2.8.3: works, but kernels compiled for
  sm_80/sm_90 only — slower than eager on B200 (46.7 / 67.9 tok/s
  vs eager 66.7 / 101.1 at 4bit / bf16).
- ``flash_attention_3``: ``no kernel image for execution on the
  device`` — sm_100 kernels not yet in flash_attn_interface.
- FA4 / ``flash_attention_4``: works standalone but transformers'
  integration hard-codes ``flash_attn_with_kvcache = None`` for it,
  so it can't service decode. Prefill-only, out of scope here.

New tests:
- ``tests/flex_moe_micro_bench.py``: tight probe that loads the
  model once, sweeps batch sizes, prints a sample completion per
  bucket (catches gibberish early). Supports ``--compile_mode
  {off, walker, walker_fullgraph}`` and ``--compile_opts
  {stock, unsloth_O3, inference_freeze}``.
- ``tests/flex_moe_bench.py``: add ``--backend hf_naive`` which
  imports pure ``transformers`` (no ``import unsloth``) for the
  reference HF baseline, with ``HF_ATTN_IMPL`` env var to switch
  between eager / sdpa / flash_attention_{2,3,4}.
- ``tests/flex_moe_parity.py``: add ``FLEX_MOE_COMPILE_WALKER=1``
  env var to exercise the compile wrap through the parity harness.
2026-04-22 17:27:41 +00:00
..
python Add configurable PyTorch mirror via UNSLOTH_PYTORCH_MIRROR env var (#5024) 2026-04-15 11:39:11 +04:00
qlora Revert "[pre-commit.ci] auto fixes from pre-commit.com hooks" 2025-12-01 07:24:58 -08:00
saving Add regression test for shell injection fix in GGML conversion (#4773) 2026-04-02 00:10:47 -07:00
sh Add configurable PyTorch mirror via UNSLOTH_PYTORCH_MIRROR env var (#5024) 2026-04-15 11:39:11 +04:00
studio/install Add ROCm test suite for PR #4720 (#4824) 2026-04-11 04:44:13 -07:00
utils feat: Add cactus QAT scheme support (#4679) 2026-04-15 07:40:03 -07:00
__init__.py Qwen 3, Bug Fixes (#2445) 2025-04-30 22:38:39 -07:00
flex_fastlm_bench.py inference: add AGPLv3 license headers 2026-04-21 13:19:01 +00:00
flex_fastlm_smoke.py inference: add AGPLv3 license headers 2026-04-21 13:19:01 +00:00
flex_lazy_batch_smoke.py [pre-commit.ci] auto fixes from pre-commit.com hooks 2026-04-21 14:58:27 +00:00
flex_lazy_live_smoke.py [pre-commit.ci] auto fixes from pre-commit.com hooks 2026-04-21 14:58:27 +00:00
flex_moe_bench.py flex/moe: compile_walker option — 2x decode throughput on Qwen3 MoE 2026-04-22 17:27:41 +00:00
flex_moe_micro_bench.py flex/moe: compile_walker option — 2x decode throughput on Qwen3 MoE 2026-04-22 17:27:41 +00:00
flex_moe_parity.py flex/moe: compile_walker option — 2x decode throughput on Qwen3 MoE 2026-04-22 17:27:41 +00:00
flex_moe_smoke.py flex: fix Qwen3 MoE smoke regressions (dtype / MoE MLP / peft patching) 2026-04-22 10:46:44 +00:00
flex_sleep_mode_smoke.py [pre-commit.ci] auto fixes from pre-commit.com hooks 2026-04-21 14:58:27 +00:00
run_all.sh fix: add tokenizers to no-torch deps and TORCH_CONSTRAINT for arm64 macOS py313+ (#4748) 2026-04-01 06:12:17 -07:00
test_cli_export_unpacking.py studio: stream export worker output into the export dialog (#4897) 2026-04-14 08:55:43 -07:00
test_get_model_name.py feat: Add support for OLMo-3 model (#4678) 2026-04-15 07:39:11 -07:00
test_loader_glob_skip.py Add unit tests for HfFileSystem glob skip guard (#4854) 2026-04-06 08:54:36 -07:00
test_model_registry.py Revert "[FIX] Vllm guided decoding params (#3662)" 2025-12-01 05:43:45 -08:00
test_raw_text.py fix: check find() return value before adding offset in try_fix_tokenizer (#4923) 2026-04-09 06:15:46 -07:00