An Ampere fork of vLLM v0.23.0 (+ FlashInfer v0.6.12) that un-gates W4A8 (int4 weights + int8
activations) and adds native int8 kernels upstream restricts to Hopper. Built from source for
sm_80 (A100) and sm_86 (RTX 3090 / A40 / A6000 / A10).
Image: ghcr.io/avesed/vllm-ampere-optimized
W4A8 is a strong serving quant — int4 weights cut decode bandwidth, int8 activations speed up prefill. Marlin can run it on Ampere, but vLLM gates its W4A8 path to Hopper: on an Ampere GPU a W4A8 checkpoint crashes at load, so Ampere users are stuck on W4A16. This fork routes W4A8 through Marlin so it runs.
patches/0001, upstream #38066) — int4-weight + int8-act through Marlin.patches/0002) — completes the W4A8 small-batch decode path.patches/0003) — keys the torch.compile cache on the quant scheme.patches/0005–0006) — --marlin-input-dtype int8 (or env
VLLM_MARLIN_INPUT_DTYPE=int8) turns a W4A16 checkpoint into W4A8 at serve time, for dense and MoE.flashampere/marlin/) — the fork owns its W4A8/W4A16 Marlin GEMM
as a plugin-selected .so (bit-exact vs stock, built in the image for sm_80+sm_86), so the int8
path survives upstream refactors.flashampere/, opt-in VLLM_FLASHAMPERE=1) — composable Ampere
attention legs: fp16-accumulate PV prefill (GeForce RTX-30 only; +1–4% long-context TTFT), a vendored
XQA decode kernel for head_dim-512 (gemma-4) and MTP spec-verify, with bit-faithful fallback to stock
FA. A per-model-architecture registry auto-applies validated defaults.--speculative-config '{"method":"dspark",...}'
serving of block-diffusion draft heads (DeepSeek DSpark / z-lab DFlash); ready-made head:
Avesed/Qwen3.6-27B-DSpark.vllm/ and flashinfer/ carry the edits baked in; patches/ + scripts/revendor.sh replay them on an
upstream bump, and scripts/build_image_source.sh builds + pushes the image.
Stock vLLM won't load W4A8 on any Ampere GPU — the fork is the only way to run it. Numbers below are W4A16 → W4A8 on the same fork engine, tok/s (int4 g32 AWQ+mse, cudagraph):
| GPU · arch | model | prefill (8k) | int8 Δ | decode | batch-32 |
|---|---|---|---|---|---|
RTX 3090 ×1 · sm_86 | 9B dense | 4.7k → 7.0k | +49% | 87 → 85 | 438 → 595 |
RTX 3090 ×2 (pp2) · sm_86 | 35B-A3B MoE | 9.1k → 10.8k | +19% | 122 → 120 | 614 → 669 |
A100 ×1 · sm_80 | 9B dense | 11.1k → 11.1k | +0% | — | — |
A100 ×1 · sm_80 | 35B-A3B MoE | 22.8k → 24.7k | +8% | — | — |
RTX 3090 ×1 · sm_86 | 26B-A4B dLLM | 4.2k → 5.5k | +32% | 178 → 213 | — |
sm_86 effect — those cards' fp16 tensor (FP32 accumulate) is
half-rate, so int8 is a ~4× compute lever. A100 (sm_80) fp16 is full-rate → int8 prefill ~0 (dense)
/ +8% (MoE). The W4A8 enabler + int4-weight decode/VRAM savings hold on every Ampere card.-pp 2 -tp 1 — TP's all-reduce eats ~half of prefill (it shrinks the 35B
int8 gain to +5%).sm_89,
so it dequant-emulates to bf16 (memory-only, ≈ W4A16 speed) — at matched accuracy: W4A8 GSM8K 95.7% / MMLU-Pro
76.4%; NVFP4 96.0% / 77.8% (N=1000/500). Two serve
requirements: --dtype bfloat16 (under int8, Gemma's large activations overflow fp16 — down-proj GEMM
dequant > 65504 → inf → NaN → blank output) and --attention-backend TRITON_ATTN (the diffusion mixed
causal/bidirectional mask isn't supported by flash-attn (wants FA4) or FlashInfer — the int8 win is the
MoE GEMM alone). Run the
cyankiwi W4A16 ckpt with
VLLM_MARLIN_INPUT_DTYPE=int8 --dtype bfloat16 --attention-backend TRITON_ATTN over the chat endpoint.docker run --gpus all -p 8000:8000 \
ghcr.io/avesed/vllm-ampere-optimized:latest \
--model Avesed/Qwen3.6-27B-INT4-W4A16 --marlin-input-dtype int8 --pipeline-parallel-size 2 --max-model-len 8192
(cu130 image needs NVIDIA driver ≥ 580.65. With NVLink use --tensor-parallel-size 2; single GPU, drop both. On a no-NVLink multi-GPU box, prefer -pp 2, or add --disable-custom-all-reduce if you use -tp 2 — custom all-reduce over PCIe + expandable_segments can crash at startup.)
Run a plain W4A16 checkpoint as W4A8 by adding --marlin-input-dtype int8 (dense or MoE).
No Docker? A from-source wheel (sm_80+sm_86) is on
Releases — pip install it (needs torch 2.11
--marlin-input-dtype int8.python quantize/quantize_w4a8.py <hf-model> <out-dir> — best quality = the AWQ + mse + g32 recipe in quantize/README.mdBuilt on vllm-project/vllm (Apache-2.0); W4A8 enablement follows upstream #38066.
116 commits
1 commits
Python
67.4%
Cuda
11.7%
HTML
8.7%
C++
7.4%
Rust
3.3%
An Ampere fork of vLLM v0.23.0 (+ FlashInfer v0.6.12) that un-gates W4A8 (int4 weights + int8
activations) and adds native int8 kernels upstream restricts to Hopper. Built from source for
sm_80 (A100) and sm_86 (RTX 3090 / A40 / A6000 / A10).
Image: ghcr.io/avesed/vllm-ampere-optimized
W4A8 is a strong serving quant — int4 weights cut decode bandwidth, int8 activations speed up prefill. Marlin can run it on Ampere, but vLLM gates its W4A8 path to Hopper: on an Ampere GPU a W4A8 checkpoint crashes at load, so Ampere users are stuck on W4A16. This fork routes W4A8 through Marlin so it runs.
patches/0001, upstream #38066) — int4-weight + int8-act through Marlin.patches/0002) — completes the W4A8 small-batch decode path.patches/0003) — keys the torch.compile cache on the quant scheme.patches/0005–0006) — --marlin-input-dtype int8 (or env
VLLM_MARLIN_INPUT_DTYPE=int8) turns a W4A16 checkpoint into W4A8 at serve time, for dense and MoE.flashampere/marlin/) — the fork owns its W4A8/W4A16 Marlin GEMM
as a plugin-selected .so (bit-exact vs stock, built in the image for sm_80+sm_86), so the int8
path survives upstream refactors.flashampere/, opt-in VLLM_FLASHAMPERE=1) — composable Ampere
attention legs: fp16-accumulate PV prefill (GeForce RTX-30 only; +1–4% long-context TTFT), a vendored
XQA decode kernel for head_dim-512 (gemma-4) and MTP spec-verify, with bit-faithful fallback to stock
FA. A per-model-architecture registry auto-applies validated defaults.--speculative-config '{"method":"dspark",...}'
serving of block-diffusion draft heads (DeepSeek DSpark / z-lab DFlash); ready-made head:
Avesed/Qwen3.6-27B-DSpark.vllm/ and flashinfer/ carry the edits baked in; patches/ + scripts/revendor.sh replay them on an
upstream bump, and scripts/build_image_source.sh builds + pushes the image.
Stock vLLM won't load W4A8 on any Ampere GPU — the fork is the only way to run it. Numbers below are W4A16 → W4A8 on the same fork engine, tok/s (int4 g32 AWQ+mse, cudagraph):
| GPU · arch | model | prefill (8k) | int8 Δ | decode | batch-32 |
|---|---|---|---|---|---|
RTX 3090 ×1 · sm_86 | 9B dense | 4.7k → 7.0k | +49% | 87 → 85 | 438 → 595 |
RTX 3090 ×2 (pp2) · sm_86 | 35B-A3B MoE | 9.1k → 10.8k | +19% | 122 → 120 | 614 → 669 |
A100 ×1 · sm_80 | 9B dense | 11.1k → 11.1k | +0% | — | — |
A100 ×1 · sm_80 | 35B-A3B MoE | 22.8k → 24.7k | +8% | — | — |
RTX 3090 ×1 · sm_86 | 26B-A4B dLLM | 4.2k → 5.5k | +32% | 178 → 213 | — |
sm_86 effect — those cards' fp16 tensor (FP32 accumulate) is
half-rate, so int8 is a ~4× compute lever. A100 (sm_80) fp16 is full-rate → int8 prefill ~0 (dense)
/ +8% (MoE). The W4A8 enabler + int4-weight decode/VRAM savings hold on every Ampere card.-pp 2 -tp 1 — TP's all-reduce eats ~half of prefill (it shrinks the 35B
int8 gain to +5%).sm_89,
so it dequant-emulates to bf16 (memory-only, ≈ W4A16 speed) — at matched accuracy: W4A8 GSM8K 95.7% / MMLU-Pro
76.4%; NVFP4 96.0% / 77.8% (N=1000/500). Two serve
requirements: --dtype bfloat16 (under int8, Gemma's large activations overflow fp16 — down-proj GEMM
dequant > 65504 → inf → NaN → blank output) and --attention-backend TRITON_ATTN (the diffusion mixed
causal/bidirectional mask isn't supported by flash-attn (wants FA4) or FlashInfer — the int8 win is the
MoE GEMM alone). Run the
cyankiwi W4A16 ckpt with
VLLM_MARLIN_INPUT_DTYPE=int8 --dtype bfloat16 --attention-backend TRITON_ATTN over the chat endpoint.docker run --gpus all -p 8000:8000 \
ghcr.io/avesed/vllm-ampere-optimized:latest \
--model Avesed/Qwen3.6-27B-INT4-W4A16 --marlin-input-dtype int8 --pipeline-parallel-size 2 --max-model-len 8192
(cu130 image needs NVIDIA driver ≥ 580.65. With NVLink use --tensor-parallel-size 2; single GPU, drop both. On a no-NVLink multi-GPU box, prefer -pp 2, or add --disable-custom-all-reduce if you use -tp 2 — custom all-reduce over PCIe + expandable_segments can crash at startup.)
Run a plain W4A16 checkpoint as W4A8 by adding --marlin-input-dtype int8 (dense or MoE).
No Docker? A from-source wheel (sm_80+sm_86) is on
Releases — pip install it (needs torch 2.11
--marlin-input-dtype int8.python quantize/quantize_w4a8.py <hf-model> <out-dir> — best quality = the AWQ + mse + g32 recipe in quantize/README.mdBuilt on vllm-project/vllm (Apache-2.0); W4A8 enablement follows upstream #38066.
116 commits
1 commits
Python
67.4%
Cuda
11.7%
HTML
8.7%
C++
7.4%
Rust
3.3%