Skip to content

[RDNA2] INT4 PLE table on the upstream PLE path (VLLM_PLE_QUANT_DIR) - #49

Merged
BlivionIaG merged 2 commits into
rdna_extrasfrom
feat/ple-int4
Oct 11, 2026
Merged

BlivionIaG merged 2 commits into
rdna_extrasfrom
feat/ple-int4

Conversation

@BlivionIaG

@BlivionIaG BlivionIaG commented Oct 11, 2026 •

Copy link
Copy Markdown

Serves the Flash-Next PLE n-gram table as INT4 on the upstream PLE path.

Upstream's PLE offload keeps the table in BF16 (95 GB of host RAM). With VLLM_PLE_QUANT_DIR=/path/to/ples_int4 (primitive-ai/Qwen3.8-Flash-Next-PLE-quant), each rank loads its rows of the INT4 group-16 table (30 GB total) into upstream's pinned storage and dequantizes on lookup. Unset, nothing changes.

Changes

  • Qwen4ExpPLEInt4EmbeddingMethod + Triton UVA lookup kernel (common/ngram_embedding.py). Other table layouts are rejected.
  • AMD/NVIDIA loaders skip the checkpoint's BF16 table when the INT4 table is used.
  • serve_validate.sh: LOAD_HOOK to run real-traffic workloads against the live server.

Tests: test_ple.py 73/73 (3 new), test_ple_amd.py 8/8 on gfx1030.

Validation (4× V620, Flash-Next W4A16, TP=4, F&P): gates, 4 cells, stall probe, agentic traffic (1k c=8, 16k c=6, 32k c=4).

Cells: prefill tok/s/req · decode tok/s/req · TTFT s · ITL median ms · aggregate output tok/s.

Table Gates Host RAM peak 1k c=1 1k c=8 16k c=1 16k c=8 Agentic (1k c=8 / 16k c=6 / 32k c=4)
BF16, MTP0 PASS, PPL 4.80 ~160 GB 2006 · 45.0 · 0.51 · 22.2 · 43.1 524 · 25.8 · 1.95 · 35.2 · 188.0 2117 · 44.5 · 7.74 · 22.5 · 33.3 1078 · 13.5 · 15.2 · 35.3 · 89.4 —
INT4, MTP0 PASS, PPL 4.83 90 GB 2015 · 45.0 · 0.51 · 22.2 · 43.1 525 · 25.9 · 1.95 · 35.0 · 188.5 2117 · 44.5 · 7.74 · 22.5 · 33.3 1078 · 13.4 · 15.2 · 35.5 · 89.3 18/18 clean; TTFT 3.1 / 30.0 / 22.5 s; 187 / 63 / 41 tok/s
BF16, MTP2 PASS, PPL 4.80 ~160 GB 2116 · 69.2 · 0.48 · 28.9 · 65.1 936 · 29.1 · 1.09 · 60.7 · 204.5 2052 · 69.0 · 7.99 · 29.1 · 44.9 1303 · 14.0 · 12.6 · 61.7 · 92.6 —
INT4, MTP2 PASS, PPL 4.82 95 GB 2073 · 70.4 · 0.49 · 28.8 · 66.1 947 · 29.1 · 1.08 · 60.3 · 200.6 2044 · 86.2 · 8.02 · 29.2 · 51.5 1324 · 14.5 · 12.4 · 61.9 · 95.7 18/18 clean; TTFT 2.5 / 30.7 / 24.0 s; 229 / 63 / 60 tok/s

Speed at parity with BF16; host RAM −65 to −70 GB. Stall probe unchanged (16k injection max gap 503 ms MTP0 / 548 ms MTP2).

…he upstream PLE path

Port of the fork's int4 PLE sidecar table onto upstream's PLE embedding.
VLLM_PLE_QUANT_DIR pointing at a ples_int4 directory (META.json layout
group16_int4_fp16scale_lownibblefirst, shard_<n>.safetensors with weight_i4 and
weight_scale) selects Qwen4ExpPLEInt4EmbeddingMethod: each rank copies its
vocabulary rows of the packed table and group scales into the existing
pinned-host (or device) storage, the checkpoint's BF16 table is skipped, and
lookups dequantize to the activation dtype (Triton UVA kernel for the pinned
table, torch gather for the device table). Flash-Next: 30 GB table instead of
95 GB BF16. Unset, nothing changes; other layouts are rejected.

Tests: tests/models/qwen4_exp/test_ple.py 73/73 (load across shard boundaries
+ dequant, layout rejection, pinned UVA kernel incl. rows owned by another
rank), test_ple_amd.py 8/8 on gfx1030.
Optional script run against the live server after the bench cells (URL, PORT,
SERVED, MODEL, OUT exported), e.g. tools/agentic_bench coding-agent traffic;
its PASS/FAIL line lands in the summary.
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