Skip to main content

Module simd

Module simd 

Source
Expand description

Targeted SIMD implementations to accelerate specific hot loops in bixverse

The 128-bit reduction arms go through wide, which lowers to SSE2 on x86_64 and NEON on aarch64. Both are baseline for their architecture, so both are real in a stock build, and wide keeps them to one code path.

The 256- and 512-bit arms are hand-written std::arch::x86_64 intrinsics behind #[target_feature]. wide’s wider types cannot be used here: f32x8 is only backed by __m256 when the whole crate is compiled with target_feature = "avx", which no stock build and no rextendr build does, so it would silently degrade to two SSE2 halves. #[target_feature] compiles the body unconditionally and is safe to enter behind is_x86_feature_detected!, which is what detect_simd_level provides.

The fused argmin is the exception: it needs compare-and-blend, which is the part of wide’s surface that has churned across minor releases (CmpLt deprecated in 1.5, blend in 1.6), and pinning that down across the range of versions a downstream lockfile might resolve is not worth it for one kernel. All of its arms, including 128-bit, are written per-architecture instead. The reductions only need arithmetic and reduce_add, which are stable, so they stay on wide.

The widening reductions at the bottom, which read f32 and accumulate in f64, are the other exception: wide has no f32x4 to f64x2 conversion, so their 128-bit arms are per-architecture too.

Every hand-written arm follows the same shape, so the two function-local constants mean the same thing throughout: W is the lane count forced by the intrinsic width (4, 8 or 16 for f32; 2, 4 or 8 for f64) and BLOCK = W * UNROLL is what one pass of the unrolled loop consumes. Each arm runs the block loop, folds its accumulators, sweeps any remaining whole vectors, then finishes the last < W elements scalar.

Enums§

SimdLevel
Enum for the different architectures and potential SIMD levels

Constants§

UNROLL
Independent accumulators carried through the vectorised loops.

Traits§

BixverseSimd
Trait for SIMD-accelerated dot product, replacing the ann-search-rs SimdDistance dependency.

Functions§

argmin_diff_simd_f32
Fused subtract-and-argmin over two slices of f32 (dispatch)
axpy_simd_f32
Scaled vector addition y += a * x for f32 (dispatch)
axpy_simd_f64
Scaled vector addition y += a * x for f64 (dispatch)
detect_simd_level
Function to detect which SIMD implementation to use
dot_simd_f32
SIMD dot product of two slices of f32 (dispatch)
dot_simd_f64
SIMD dot product of two slices of f64 (dispatch)
exp_shift_sum_simd_f32
Shifted exponential dst = exp(src - shift) with its sum.
hsum_avx_f64⚠
Horizontal sum of a 256-bit f64 vector.
hsum_sse_f64⚠
Horizontal sum of a 128-bit f64 vector.
sum_simd_f32
SIMD sum of a slice of f32 (dispatch)
sum_simd_f64
SIMD sum of a slice of f64 (dispatch)
sum_squared_dev_simd_f32
SIMD sum of squared deviations of a slice of f32 (dispatch)
sum_squared_dev_simd_f64
SIMD sum of squared deviations of a slice of f64 (dispatch)
sum_squared_dev_widen_simd_f32
Widening sum of squared deviations of a slice of f32 (dispatch)
sum_squares_simd_f32
SIMD squared sum of a slice of f32 (dispatch)
sum_widen_simd_f32
Widening sum of a slice of f32, accumulated in f64 (dispatch)