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§
- Simd
Level - Enum for the different architectures and potential SIMD levels
Constants§
- UNROLL
- Independent accumulators carried through the vectorised loops.
Traits§
- Bixverse
Simd - 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 * xfor f32 (dispatch) - axpy_
simd_ f64 - Scaled vector addition
y += a * xfor 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)