Repository navigation
Commit 64b68de
perf: speed up top-p sampling for large vocabularies (#1232)
## Description
Optimizes token sampling for large-vocabulary models (e.g. Gemma 4 E2B,
262k vocab), where the previous full-vocabulary sort in top-p dominated
per-token latency.
Two changes in `sampler.cpp`:
- **`mask_topp`**: replaces the `O(n log n)` sort over all logits with a
logit-space histogram (`kBins=2048`) that locates the nucleus threshold
in two `O(n)` passes — no sort, no per-token vocab-sized allocation.
Binning in logit space (rather than probability space) keeps uniform
resolution for both peaked and flat distributions.
- **`softmax`**: skips `exp()` on logits already masked to `lowest()` by
top-k/top-p. The result underflows to zero anyway, and the call is slow
on device.
On an iPhone 17 Pro with Gemma 4 E2B (int4), per-token sampling drops
from ~45 ms to ~10 ms. The histogram approximates the exact sort-based
nucleus; the resulting sampled distribution is statistically equivalent
(verified the kept-mass fraction stays within <1% of the exact nucleus
across peaked, flat, and sharp distributions).
### Introduces a breaking change?
- [ ] Yes
- [x] No
### Type of change
- [ ] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [x] Other (chores, tests, code style improvements etc.)
### Tested on
- [x] iOS
- [ ] Android
### Testing instructions
1. Run an LLM with a large vocabulary and a non-zero temperature with
`topP` set (e.g. Gemma 4 E2B with `temperature: 0.8`, `topP: 0.9`).
2. Generate a long response and observe tokens/sec.
3. Confirm output remains coherent and sampling is unchanged in
character (still stochastic, not greedy).
Greedy decoding (`temperature: 0`) is unaffected — it bypasses this path
entirely.
### Screenshots
<!-- N/A -->
### Related issues
<!-- N/A -->
### Checklist
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [x] My changes generate no new warnings
### Additional notes
The histogram is an approximation bounded by bin granularity
(`kBins=2048` over a `kRange=40` logit span). This is intentional: exact
top-p over a 262k vocab where the nucleus can exceed 100k tokens is
inherently expensive, and the sampling outcome is statistically
indistinguishable from the exact version.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent aea5db0 commit 64b68de
1 file changed
Lines changed: 52 additions & 41 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
39 | 42 | | |
40 | 43 | | |
41 | 44 | | |
| |||
141 | 144 | | |
142 | 145 | | |
143 | 146 | | |
144 | | - | |
145 | | - | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
146 | 151 | | |
147 | 152 | | |
148 | 153 | | |
149 | 154 | | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
160 | 170 | | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
165 | 177 | | |
166 | | - | |
| 178 | + | |
167 | 179 | | |
168 | 180 | | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | 181 | | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
184 | 191 | | |
185 | 192 | | |
186 | 193 | | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
192 | 197 | | |
193 | 198 | | |
194 | | - | |
| 199 | + | |
195 | 200 | | |
196 | 201 | | |
197 | 202 | | |
| |||
210 | 215 | | |
211 | 216 | | |
212 | 217 | | |
213 | | - | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
214 | 221 | | |
215 | 222 | | |
216 | 223 | | |
217 | 224 | | |
218 | 225 | | |
219 | 226 | | |
220 | | - | |
221 | 227 | | |
222 | 228 | | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
223 | 233 | | |
224 | 234 | | |
225 | 235 | | |
226 | | - | |
227 | 236 | | |
228 | | - | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
229 | 240 | | |
230 | 241 | | |
231 | 242 | | |
| |||
0 commit comments