Skip to content

perf(turbo): optimize AVX2/AVX512 distance kernels with FMA and ILP unrolling - #771

Open
thlurte wants to merge 1 commit into
alibaba:mainfrom
thlurte:perf-turbo-simd-distance
Open

thlurte wants to merge 1 commit into
alibaba:mainfrom
thlurte:perf-turbo-simd-distance

Conversation

@thlurte

@thlurte thlurte commented Sep 18, 2026

Copy link
Copy Markdown

Fixes #706.

Summary of Changes

This PR optimizes the FP32 distance kernels (Squared Euclidean and Inner Product) in Turbo for both AVX2 and AVX-512 target architectures:

  1. Instruction-Level Parallelism (ILP):
    • In AVX2 kernels: unrolled the main loop by 32 elements per iteration across 4 independent vector accumulators (acc0, acc1, acc2, acc3). This hides the 4-cycle FMA pipeline latency and saturates CPU execution ports.
    • In AVX-512 kernels: unrolled by 32 elements per iteration across dual ZMM accumulators.
  2. Fused Multiply-Add (FMA):
    • Replaced unfused multiply-add sequences (_mm256_add_ps(..., _mm256_mul_ps(...)) and _mm512_add_ps(..., _mm512_mul_ps(...))) with single-cycle _mm256_fmadd_ps and _mm512_fmadd_ps.
  3. Optimized Horizontal Tree Reduction:
    • Replaced slow consecutive _mm_hadd_ps instructions in AVX2 with a fast shuffle tree (_mm_movehdup_ps, _mm_movehl_ps, _mm_add_ss).
  4. AVX-512 Masked Tail Reductions:
    • Trailing dimensions ($<16$) are now loaded and processed using AVX-512 opmasks (_mm512_maskz_loadu_ps), eliminating scalar fallback loops.
  5. Cosine Distance:
    • Both AVX2 and AVX-512 cosine routines delegate to inner product and automatically inherit the full speedup for single-vector and batched calls.

Verification

  • Formatted with repository clang-format (--dry-run --Werror passes with 0 violations).
  • Ran ./build/bin/turbo_fp32_quantizer_test: 7/7 tests passed across all 14 test dimensions ($D \in {2, 7, 8, 15, 16, 17, 31, 32, 33, 63, 64, 65, 126, 130}$).
  • Ran ./build/bin/flat_turbo_index_test: 26/26 tests passed (end-to-end index build, save, reload, and query across FP32, FP16, INT8, INT4).

…lling, and fast horizontal reduction

- Replace non-fused multiply-adds with _mm256_fmadd_ps and _mm512_fmadd_ps
- 4-way ILP unrolling (32 elements/iter across 4 accumulators) in AVX2 kernels to hide 4-cycle FMA latency
- Dual accumulator 32-element unrolling in AVX-512 kernels
- Replace slow consecutive _mm_hadd_ps in AVX2 with fast shuffle tree (_mm_movehdup_ps / _mm_movehl_ps / _mm_add_ss)
- Implement AVX-512 masked tail loads and reductions, avoiding scalar fallback loops
- Fixes alibaba#706
@CLAassistant

CLAassistant commented Sep 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@richyreachy

Copy link
Copy Markdown
Collaborator

Hi thlurte,

Thank you for contributing this optimization. We appreciate the effort to improve the FP32 distance kernels through FMA, loop unrolling, and horizontal reduction changes.

We’d like to evaluate the changes more thoroughly and benchmark the performance on AVX2 and AVX512 hardware etc.

If you have benchmark results, please share the CPU model, compiler and build flags, vector dimensions, and before-and-after measurements. Those would be very helpful for the evaluation.

Thanks again for the contribution and your patience while it is reviewed.

@thlurte

thlurte commented Sep 21, 2026

Copy link
Copy Markdown
Author

Hi thlurte,

Thank you for contributing this optimization. We appreciate the effort to improve the FP32 distance kernels through FMA, loop unrolling, and horizontal reduction changes.

We’d like to evaluate the changes more thoroughly and benchmark the performance on AVX2 and AVX512 hardware etc.

If you have benchmark results, please share the CPU model, compiler and build flags, vector dimensions, and before-and-after measurements. Those would be very helpful for the evaluation.

Thanks again for the contribution and your patience while it is reviewed.

Hi @richyreachy,

Thank you for the review! Here are the empirical benchmark measurements comparing the baseline kernels against the optimized kernels in this PR.

Environment & Setup

  • CPU: AMD Ryzen 5 8645HS (Zen 4 microarchitecture, 6 cores / 12 threads, AVX2 + AVX-512)
  • Compilers tested:
    • gcc (GCC) 16.2.1 20260810
    • clang version 22.1.8
  • Build flags: -O3 -mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx2 -mfma -DNDEBUG
  • Workload: 1,000,000 warm iterations per dimension using pseudo-random FP32 vectors sampled from U(-1.0, 1.0) (matching the methodology in tests/turbo/turbo_fp32_quantizer_test.cc), with compiler barriers (memory clobber) to prevent dead-code elimination or loop hoisting.

1. AVX2 Benchmarks

Squared Euclidean (L2) Distance

Dimension Baseline (ns) Optimized (ns) Speedup (GCC) Speedup (Clang)
64 3.67 3.18 1.15x 1.37x
128 7.18 5.48 1.31x 1.41x
256 15.62 10.46 1.49x 1.59x
512 33.96 20.81 1.63x 1.66x
768 51.81 31.50 1.65x 1.68x
1024 74.99 42.56 1.76x 1.82x
1536 120.43 65.44 1.84x 1.99x

Inner Product (IP) Distance

Dimension Baseline (ns) Optimized (ns) Speedup (GCC) Speedup (Clang)
64 3.19 3.07 1.04x 1.38x
128 6.06 5.27 1.15x 1.29x
256 13.10 10.23 1.28x 1.28x
512 32.35 20.78 1.56x 1.48x
768 46.80 32.05 1.46x 1.56x
1024 65.02 43.31 1.50x 1.47x
1536 111.39 65.94 1.69x 1.79x

2. AVX-512 Benchmarks

Squared Euclidean (L2) & Inner Product (IP)

Dimension Metric Baseline (ns) Optimized (ns) Speedup
512 L2 23.38 22.56 1.04x
768 L2 33.97 32.93 1.03x
1024 L2 45.64 43.65 1.05x (up to 1.21x on Clang)
1536 L2 72.28 67.37 1.07x
768 IP 37.63 34.21 1.10x
1024 IP 46.89 44.41 1.06x

Key Architectural Takeaways

  1. AVX2: The 4-way ILP unrolling (4 independent __m256 accumulators) effectively hides the 4-cycle FMA latency, while replacing sequential _mm_hadd_ps with shuffle trees avoids port pressure at reduction time. This yields 1.5x–1.9x throughput gains across typical vector dimensions (512–1536).
  2. AVX-512: Dual accumulators provide steady latency reductions, and masked loads (_mm512_maskz_loadu_ps) eliminate the scalar loop fallback for tail elements.

Please let me know if you would like me to test any additional dimensions or target architectures!

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.

[Feature]: Add AVX2/AVX512 SIMD Kernels for Distance in Turbo

3 participants