Commit 4a52ad4
Route Hamming code sizes to the fastest kernel, and accept ragged sizes
Summary:
`faiss::hammings()` had two problems. It threw unless the code size was a whole number of 64-bit words, even though the other Hamming entry points (`hammings_knn_hc`, `hamming_range_search`) have always accepted ragged sizes. And for aligned sizes it always used the bit-level `hammings_impl<nbits>` kernels, never the hand-written `HammingComputer` family, which is substantially faster at some sizes.
Together those forced callers who cared about either case to reach past `hammings()` into `with_simd_level_a0_spr` and `with_HammingComputer` — faiss internals — and hand-roll the sweep plus a routing rule. Laser does exactly this today in `KnnFaissBinaryIndex::measureAllCentroids` (D115840549), and can drop all of it after this.
`hammings_fixSL` now takes the `HammingComputer` path when the size is ragged, or when `prefer_hamming_computer()` says the computer beats the word kernel there. That predicate is `constexpr` over `THE_SIMD_LEVEL`, because which sizes qualify depends on the ISA. Sizes it does not name keep the kernels they use today, so aligned sizes with no dedicated computer (24, 40, 48, 56, 128, ...) are unaffected by design.
## Which sizes, and why
Both kernels measured in one process, interleaved rep by rep, at na=1/nb=65536 and na=256/nb=4096. Negative means the computer wins.
| ncodes | static AVX2 | dynamic dispatch (AVX512) |
| --- | --- | --- |
| 8 | kernel wins 46% | kernel wins 202% |
| 16 | **computer wins 25%** | kernel wins 45% |
| 32 | **computer wins 23%** | kernel wins 27% |
| 64 | **computer wins 42%** | **computer wins 73%** |
| 4, 20 | tie — already routed to the computer | tie |
| 24/40/48/56/128/160 | kernel wins 32-98% | kernel wins 42-144% |
So only 64 qualifies at every level. `hamming<512>` has no SIMD specialization above 256 bits on x86 — it is a plain scalar popcount loop — and compiling it with AVX-512 flags makes it markedly worse rather than better (15.0 ns/pair, versus 6.7 under AVX2). Size 8 never qualifies, which is worth noting because Laser's current rule assumes it does.
## FAISS_NOINLINE removed
An earlier version of this diff put `FAISS_NOINLINE` on the ragged helper, because inlining it doubled `hammings_fixSL` and slowed the sizes sharing the runtime-nwords loop. Re-measuring after the routing change, that no longer reproduces anywhere: with 16/32/64 moved off the switch, inlining is neutral-to-better in both build modes (ncodes 24: -10.1% static, -3.1% DD; ragged sizes -3 to -12%). The attribute and its `platform_macros.h` macro are dropped; nothing else in faiss used it.
## Net effect
Versus the previous state of this diff. Interleaved A/B, one code size per process, 300 samples per cell.
| ncodes | static AVX2 | dynamic dispatch (AVX512) |
| --- | --- | --- |
| 16 | **-25.2%** | -0.5% |
| 32 | **-25.2%** | -0.2% |
| 64 | **-47.3%** | **-83.3%** (15.0 -> 2.50 ns/pair) |
| 12 / 20 / 33 (ragged) | -7.3 / -11.8 / -5.1% | -0.2 / -10.5 / -4.0% |
| 8, 40, 48, 56, 128 | within noise (<=1.6%) | within noise (<=2.6%) |
| **24** | **+19.6%** | -3.5% |
## Caveats
**ncodes 24, static AVX2, +19.6%.** Not explained. Retired instructions per pair are identical (36.86 vs 36.83), both hot loops are 32-byte aligned, and DSB uops, uops issued/retired, resource stalls, memory stalls, 4K aliasing and branch mispredicts are all unchanged; the same instruction sequence simply takes 28% more cycles. This size has swung 30-50% from unrelated code motion three separate times during this work, so the working theory is that its runtime-nwords loop is unusually placement-sensitive on this core and the change landed it badly. Plausible follow-up is to give that path its own out-of-line function so it stops sharing layout with the switch; not attempted here.
**Measured only on Intel Cooper Lake** (Xeon Platinum 8339HC), `mode/opt`. `prefer_hamming_computer()` is a per-ISA table, and AVX-512 behaves quite differently on AMD Zen, so the AVX512 rows should be re-measured before relying on them there. Levels that were not measured (NONE, NEON, SVE, RVV) deliberately keep their current kernels. AVX512_SPR is grouped with AVX512 on the mechanism above rather than on a measurement, since no SPR host was available.
Differential Revision: D1159825411 parent 1f93154 commit 4a52ad4
3 files changed
Lines changed: 82 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | | - | |
| 114 | + | |
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
298 | 298 | | |
299 | 299 | | |
300 | 300 | | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
301 | 336 | | |
302 | 337 | | |
303 | 338 | | |
| |||
364 | 399 | | |
365 | 400 | | |
366 | 401 | | |
367 | | - | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
368 | 406 | | |
369 | 407 | | |
370 | 408 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
316 | 316 | | |
317 | 317 | | |
318 | 318 | | |
319 | | - | |
| 319 | + | |
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
| |||
333 | 333 | | |
334 | 334 | | |
335 | 335 | | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
0 commit comments