Skip to content

feat: swordfish kernels for Blackwell#1707

Merged
AlpinDale merged 31 commits into
mainfrom
feat/swordfish
Jul 12, 2026
Merged

feat: swordfish kernels for Blackwell#1707
AlpinDale merged 31 commits into
mainfrom
feat/swordfish

Conversation

@AlpinDale

@AlpinDale AlpinDale commented Jul 11, 2026

Copy link
Copy Markdown
Member

Swordfish is a Blackwell-native (sm100 and sm110) GEMM kernel family descended from the same lineage as Marlin and Machete. Supported modes: symmetric GPTQ int4 (uint4b8) and int8 (uint8b128), AWQ (uint4 with zero points), desc_act/act_order checkpoints, fused MoE, fp16 and bf16 activations, group sizes 32/64/128 and channelwise (all with the full tcgen05 prefill path; channelwise checkpoints replicate their single scale row to group 128 at weight load, a few hundred KB of duplicate scales per layer). APHRODITE_SWORDFISH_DETERMINISTIC=1 forces run-stable decode reductions. Auto-selected on supported hardware; force with --linear-backend swordfish (dense) and --moe-backend swordfish (MoE). Unsupported corners (row-parallel TP with act_order, W4A8 activation quant) fall back to Marlin automatically.

Benchmarks

End-to-end serving sweep against every mixed-precision backend that runs on sm100/sm110, one checkpoint per mode, 1024-token prompts, 128 output tokens, prefix caching off. Numbers are prefill tok/s (bs=1 / bs=32) and decode tok/s (bs=1 / bs=32). Backends run bf16 activations except exllama, which is fp16-only. Machete (Hopper-only) and CutlassW4A8 (activation-quant mode) cannot run on this hardware.

swordfish_b200 swordfish_thor
Per-mode tables (all backends, with footnotes)

GPTQ int4 g128 — Llama-3.1-8B

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 54.2k / 89.5k 344 / 7,176 7.5k / 7.1k 48 / 790
marlin 23.8k / 26.4k 312 / 7,169 2.9k / 3.0k 48 / 796
humming 25.2k / 29.3k 297 / 6,500 3.1k / 3.2k¹ 45 / 727¹
exllama (fp16) 50.4k / 82.7k² 338 / 2,021 4.3k / 3.4k 48 / 227
conch 18.4k / 24.9k 56 / 1,713 2.6k / 2.7k 17 / 412
triton n/a³ n/a³ n/a³ n/a³

AWQ uint4 + zero points g128 — Qwen2.5-3B

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 82.6k / 193.7k 416 / 10,426 15.4k / 15.1k 96 / 1,846
marlin 46.9k / 60.3k 375 / 9,865 6.4k / 6.7k 96 / 1,905
triton 33.3k / 59.1k 58 / 1,832 6.0k / 4.8k 32 / 867
conch 36.7k / 55.1k 83 / 2,569 5.6k / 5.8k 38 / 983
humming n/a⁴ n/a⁴ n/a⁴ n/a⁴

GPTQ int8 g128 — Qwen2.5-3B

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 94.1k / 193.5k 412 / 10,129 12.1k / 14.0k 64 / 1,458
marlin 41.4k / 51.6k 344 / 9,208 5.0k / 5.2k 63 / 1,439
exllama (fp16) 75.0k / 169.5k² 284 / 5,390 8.8k / 8.9k 63 / 490
conch 37.5k / 57.3k 83 / 2,604 5.8k / 6.0k 37 / 976
humming n/a⁴ n/a⁴ n/a⁴ n/a⁴

GPTQ int4 with desc_act — Mistral-7B-v0.2

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 62.4k / 87.7k 340 / 7,163 7.2k / 6.1k 56 / 836
marlin 22.5k / 25.0k 253 / 6,284 2.8k / 2.8k 55 / 856
exllama (fp16) 51.0k / 80.7k² 342 / 2,015 4.3k / 3.4k 56 / 233

Fused MoE, GPTQ int4 g128 — Qwen1.5-MoE-A2.7B (60 experts, top-4)

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 56.4k / 148.9k 426 / 5,928 8.4k / 12.0k 109 / 639
marlin 41.2k / 67.0k 389 / 5,746 6.5k / 7.7k 103 / 655
humming 48.4k / 70.7k 388 / 5,678 6.6k / 8.2k¹ 100 / 623¹

GPTQ int8 channelwise — TinyLlama-1.1B

backend B200 prefill B200 decode Thor prefill Thor decode
swordfish 169.4k / 494.2k 820 / 20,547 29.6k / 37.1k 178 / 3,365
allspark⁵ 101.8k / 516.6k 774 / 20,456 15.6k / 36.6k 169 / 3,253
marlin 90.0k / 140.9k 661 / 16,942 14.8k / 15.8k 173 / 3,351
conch 81.4k / 154.4k 195 / 6,028 15.6k / 16.4k 103 / 2,387
humming n/a⁴ n/a⁴ n/a⁴ n/a⁴
exllama n/a⁶ n/a⁶ n/a⁶ n/a⁶
triton n/a⁶ n/a⁶ n/a⁶ n/a⁶

¹ humming shipped no sm110 support (no heuristics entry, and NVML roofline queries Jetson cannot answer); this branch adds a compat shim mapping Thor onto its sm100 heuristics, which is what makes the Thor cells above possible.
² exllama reconstructs fp16 weights and runs dense GEMM above its M threshold, which briefly held the large-batch prefill cells; swordfish now ships the same strategy as its own large-M tier (all modes including zero points, act_order folded into the weight scatter) and takes those cells back with room to spare.
³ upstream TritonW4A16 bug: a qzeros shape assert trips on symmetric-GPTQ placeholder tensors.
⁴ humming's NVRTC JIT fails to compile its zero-point and int8 configurations on this stack (both boxes).
⁵ AllSpark is channelwise-int8-only — it rejects every other mode in this sweep (group 128, 4-bit, zero points, act_order, MoE), so this is its one table. It shipped arch-gated to Ampere; this branch builds it with 8.0+PTX, lifts the capability gate, and exposes it as --linear-backend allspark. Its former B200 decode lead (the M=32-48 window) is gone: the [17,48] band now dispatches to the fused atomic grid on many-SM parts, decode zeroes its output with a compute kernel instead of a memset (a per-GEMM copy-engine round trip inside captured decode graphs), and channelwise decode reads its scale row once instead of re-expanding replicated rows.
⁶ exllama rejects channelwise outright ("group size must be positive"); triton's W4A16 kernel is 4-bit only.

Known residuals, all on Thor decode at bs=32 (the M 17-48 window on 20 SMs, marlin's home regime): awq -3%, moe -2%, actorder -2%, gptq4 -0.8%. Kernel-level the window sits at 0.94-1.22 of marlin after the column-quad claims; the remaining few percent needs a cooperative wide-tile decode kernel, tracked as follow-up. The same workloads win full requests on Thor regardless — prefill is 2-3x ahead in every mode.

Channelwise, kernel level

Swordfish carries channelwise by replicating the single scale row to group 128 at weight load (K/128 x N fp16, ~256 KB per 4096² layer), which buys it the full grouped machinery — tcgen05 prefill and the dense-GEMM tier. vs marlin: B200 prefill M=256-8192 1.4-4.1x, decode 0.93-1.27; Thor prefill 2.0-3.0x (int4), 1.5-2.7x (int8), decode unchanged.

Op-level three-way at 4096x4096 int8 channelwise (fp16 activations, median µs per GEMM, lower is better) shows the M-structure behind the e2e table above:

M B200 swordfish / marlin / AllSpark Thor swordfish / marlin / AllSpark
1 11.7 / 14.3 / 14.2 69.4 / 71.5 / 78.6
16 12.7 / 14.6 / 14.5 73.5 / 71.4 / 77.2
32 16.8 / 15.6 / 14.6 75.1 / 71.1 / 78.1
256 27.0 / 37.7 / 42.1 94.6 / 216.2 / 185.0
1024 41.8 / 101.0 / 90.7 370 / 810 / 693
8192 215.3 / 726.4 / 195.9 2826 / 6132 / 2811

Same pattern across the other shapes: swordfish leads decode M<=16 (1.1-1.3x over both) and mid-range prefill M=256-1024 (1.4-2.6x, tcgen05); the M=17-48 band, formerly AllSpark's by 6-16%, moved to the fused atomic grid on many-SM parts and now wins or ties every cell (0.95-1.33 vs marlin, parity-plus vs AllSpark); at M>=2048 swordfish's dense tier and AllSpark converge on the same dequant-plus-cuBLAS strategy and trade places within run-to-run noise (±10%, both directions across repeat runs). Chasing this comparison on Thor exposed a stale gate: the dense tier was disabled below 100 SMs based on 4-bit measurements, but 8-bit moves twice the weight bytes through the mixed-input transform and does cross over — it now engages at M>=2048 on few-SM parts (M>=8192 for K-heavy shapes), taking Thor int8 large-M from 0.77-0.97x AllSpark to parity-or-better and 1.6-2.2x marlin.

Why

tcgen05 has no mixed-input MMA, so weight-only int4 needs a new design on this generation. NVFP4 is the main selling point of Blackwell, but there's still people out there who use GPTQ/AWQ. This is for you!

@AlpinDale AlpinDale changed the title feat: add swordfish w4a16 gemm kernels for blackwell feat: swordfish kernels for Blackwell Jul 11, 2026
@AlpinDale AlpinDale merged commit a231864 into main Jul 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant