huginnfork commited on
Commit
8a9da86
·
verified ·
1 Parent(s): 981c53f

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +65 -16
README.md CHANGED
@@ -56,23 +56,65 @@ KLD is per-token, 8 samples from `neuralmagic/calibration` (LLM split) at `max_s
56
  PPL is `wikitext-2-raw` test, non-overlapping 2048-token chunks. Baseline for both is
57
  **bf16 `Qwen/Qwen3.8-27B` itself**, so what is measured is quantisation loss and nothing else.
58
 
59
- | Model | Modules quantised | KLD vs bf16 | max-token KLD | PPL | ΔPPL |
 
 
 
 
 
 
 
60
  |---|---|---|---|---|---|
61
- | `Qwen/Qwen3.8-27B` (bf16) | — | 0 | | 6.9416 | — |
62
- | [`Qwen/Qwen3.8-27B-FP8`](https://huggingface.co/Qwen/Qwen3.8-27B-FP8) (official) | 407 | **0.0523** | 17.51 | 6.9539 | +0.18 % |
63
- | **This model** | 192 | 0.0756 | 17.95 | **6.9325** | **-0.13 %** |
64
-
65
- ### How to read this honestly
66
-
67
- The official FP8 has **lower average KLD** than this build, despite quantising more than
68
- twice as many modules. That is not a contradiction: it uses 128x128 **block** scales,
69
- whose grid has resolution along the *input* dimension, while `llm-compressor` emits one
70
- scale per *output channel*. Per-channel scaling has no resolution along the input axis at
71
- all, so a single outlier column inflates a whole row's scale. Finer element count does not
72
- imply finer where it matters.
73
-
74
- On PPL the two are not meaningfully separable both sit within noise of the bf16 parent
75
- (one slightly above, one slightly below).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  So the reasons to prefer this build are **architectural, not average-case accuracy**:
78
 
@@ -99,6 +141,13 @@ without it, vLLM's compressed-tensors loader treats the bf16 head as a quantised
99
  finds no scales, mis-loads it, and **every draft is rejected — 0 % acceptance at every
100
  position** while the head still appears to load correctly in the logs.
101
 
 
 
 
 
 
 
 
102
  ## Smoke tests
103
 
104
  Text generation, vision, and MTP key presence all pass:
 
56
  PPL is `wikitext-2-raw` test, non-overlapping 2048-token chunks. Baseline for both is
57
  **bf16 `Qwen/Qwen3.8-27B` itself**, so what is measured is quantisation loss and nothing else.
58
 
59
+ **Two KLD columns, because one number cannot be fair to both checkpoints.** The official
60
+ release is DeepSeek-format FP8, which has to be dequantised to plain bf16 before it will
61
+ run at all on Blackwell — and a dequantised checkpoint runs with **bf16 activations**. Our
62
+ checkpoint, loaded normally, still applies its scheme's **dynamic FP8 activation quant**.
63
+ Comparing those two directly measures W8A8 against W8A16 and flatters whichever model was
64
+ dequantised. So both are reported both ways.
65
+
66
+ | Model | Modules quantised | KLD (weight-only) | KLD (as deployed) | PPL | ΔPPL |
67
  |---|---|---|---|---|---|
68
+ | `Qwen/Qwen3.8-27B` (bf16) | — | 0 | 0 | 6.9416 | — |
69
+ | [`Qwen/Qwen3.8-27B-FP8`](https://huggingface.co/Qwen/Qwen3.8-27B-FP8) (official) | 407 | 0.0523 | 0.1001 | 6.9539 | +0.18 % |
70
+ | **This model** | 192 | **0.0362** | **0.0756** | **6.9325** | **-0.13 %** |
71
+
72
+ *Weight-only* = weights round-tripped through the quantised format, activations bf16.
73
+ *As deployed* = the same weights plus dynamic per-token FP8 activation quantisation on
74
+ exactly the modules each checkpoint actually converts. For this build the two differ because `FP8_DYNAMIC` quantises activations; for the official they differ for the same reason.
75
+
76
+ **This build has lower divergence from the bf16 parent than the official release on both
77
+ measures** **31% lower** weight-only and **24% lower** as deployed while quantising
78
+ 192 modules to the official's 407.
79
+
80
+ On PPL the two are not meaningfully separable; both sit within noise of the bf16 parent.
81
+ A negative ΔPPL does **not** mean this build beats its own parent, only that the loss is
82
+ below measurement noise.
83
+
84
+ ### What does *not* explain the difference
85
+
86
+ The intuitive story is that scale layout matters — the official uses 128x128 **block**
87
+ scales, `llm-compressor` emits one scale per **output channel**. We tested that directly,
88
+ simulating the FP8 E4M3 round-trip on real weight tensors from this model
89
+ ([`experiment_block_scales.py`](https://github.com/huginnfork/llm-quantisation/blob/master/remote/experiment_block_scales.py)):
90
+
91
+ | scheme | #scales | rel. Frobenius err | max abs err |
92
+ |---|---|---|---|
93
+ | per-tensor | 1 | 0.02648 | 0.02065 |
94
+ | per-output-channel (this build) | 5120 | 0.02643 | 0.02065 |
95
+ | block 128x128 (official) | 5440 | 0.02643 | **0.00426** |
96
+ | *control:* INT8 per-tensor | 1 | 0.0750 | — |
97
+ | *control:* INT8 per-output-channel | 17408 | **0.0101** | — |
98
+ | *control:* INT8 block 128x128 | 5440 | 0.0144 | — |
99
+
100
+ All FP8 variants land within 0.1 % of each other — **including per-tensor, with a single
101
+ scale for the entire matrix**. The reason is that FP8 is a *floating-point* format: every
102
+ element carries its own exponent, so the scale only has to bring values into range rather
103
+ than resolve dynamic range the way a fixed-point scale must. The INT8 control shows the
104
+ method is sensitive enough to detect layout effects where they exist (a 7.4x spread) — and
105
+ that in *that* regime per-output-channel actually beats 128x128 block, having more scales.
106
+
107
+ Block scaling does buy a ~5x lower **worst-case** weight error; that is an outlier-tail
108
+ property, not an average one.
109
+
110
+ We also checked whether the vendor used a smarter rounding than round-to-nearest, by
111
+ comparing their stored weights against an RTN round-trip of the same parent tensors
112
+ ([`experiment_rounding.py`](https://github.com/huginnfork/llm-quantisation/blob/master/remote/experiment_rounding.py)):
113
+ their reconstruction error matches RTN to within 0.3 %. They used plain round-to-nearest.
114
+
115
+ So the gap is not scale layout and not rounding — it is **which modules get quantised**.
116
+ This build leaves the attention path, the SSM block and the MTP head in bf16; the official
117
+ quantises all of them.
118
 
119
  So the reasons to prefer this build are **architectural, not average-case accuracy**:
120
 
 
141
  finds no scales, mis-loads it, and **every draft is rejected — 0 % acceptance at every
142
  position** while the head still appears to load correctly in the logs.
143
 
144
+ Measured on vLLM with `--speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":1}'`
145
+ over greedy decoding of mixed chat/code/reasoning prompts:
146
+
147
+ | | draft tokens | accepted | acceptance |
148
+ |---|---|---|---|
149
+ | This model | 574 | 490 | **85.4%** |
150
+
151
  ## Smoke tests
152
 
153
  Text generation, vision, and MTP key presence all pass: