Commit aab66c6
relax codes%8 condition on Hamming distance
Summary:
`faiss::hammings()` used to `FAISS_THROW_IF_NOT(ncodes % 8 == 0)`, even though the other Hamming entry points (`hammings_knn_hc`, `hamming_range_search`) have always accepted code sizes that are not a whole number of 64-bit words. This lifts that restriction so `hammings()` matches the rest of the API.
Ragged sizes are routed to a new out-of-line helper, `hammings_ragged()`, built on the existing `HammingComputer` family (which already carries a byte tail). Multiples of 8 keep taking the word-level kernels exactly as before, so there is no behavior change for existing callers.
Also adds a `FAISS_NOINLINE` macro to `platform_macros.h` (MSVC `__declspec(noinline)` / GCC-Clang `__attribute__((noinline))`), used to keep `hammings_ragged()` out of line.
## Why FAISS_NOINLINE
Letting the compiler inline `hammings_ragged()` into `hammings_fixSL()` instantiates the whole `HammingComputer` family into that function and roughly doubles its size (3,597 -> 7,565 bytes at the AVX2 level). That measurably slows the word-level code sizes that share the runtime-nwords loop.
Benchmarked on a Xeon 8339HC (Cooper Lake, AVX-512), `mode/opt`, na=256 x nb=4096 = 1M pairs per call, one code size per process, A/B interleaved with order flipping, 300-400 samples per cell, replicated on two cores. Positive = inlining is slower, i.e. `noinline` wins.
| ncodes | static AVX2 | dynamic dispatch (AVX512) |
| --- | --- | --- |
| 8, 16, 32, 64, 128 | ~0% | ~0% |
| 24 | +3.4% | +53% |
| 40 | +5.0% | +22% |
| 48 | ~0% | +28% |
| 56 | +4.4% | +35% |
| 12, 20, 33 (ragged) | -5% | -5% to -12% |
Two distinct mechanisms, both confirmed in the disassembly:
- **Static AVX2** - the inlined version has higher register pressure and spills, adding exactly one reload per pair in the shared outer loop. Retired instruction counts (noise-free) show +1.00 instr/pair at ncodes 24/40/48/56 and 0.00 at 8/16/32/64/128.
- **Dynamic dispatch** - the popcount inner loop is a byte-identical 24-byte sequence in both builds, but out of line it starts at `%32 == 0` (one 32-byte fetch window) and inlined at `%32 == 16` (straddles two). IPC drops 3.02 -> 2.36 at identical clock. This one is a code-placement effect: it is real today but is not something `noinline` reliably controls, and it could invert on a compiler upgrade.
Note that the dedicated `ncodes` 8/16/32/64 kernels are unaffected either way - they have their own specialized `hammings_impl<nbits>` blocks that the ragged inline never touches.
The trade: the ragged path itself is ~5% slower for being out of line. That is accepted here because the word-level sizes are the common case and are the ones that were already supported.
Differential Revision: D1159825411 parent 80a1656 commit aab66c6
4 files changed
Lines changed: 76 additions & 2 deletions
File tree
- faiss
- impl
- utils
- hamming_distance
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
| 107 | + | |
107 | 108 | | |
108 | 109 | | |
109 | 110 | | |
| |||
137 | 138 | | |
138 | 139 | | |
139 | 140 | | |
| 141 | + | |
140 | 142 | | |
141 | 143 | | |
142 | 144 | | |
| |||
| 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 | + | |
301 | 320 | | |
302 | 321 | | |
303 | 322 | | |
| |||
364 | 383 | | |
365 | 384 | | |
366 | 385 | | |
367 | | - | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
368 | 399 | | |
369 | 400 | | |
370 | 401 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
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