SIMD - Experimental helpers
This page lists all operations on slices, available in the exp/simd sub-package. These helpers use Go 1.27's portable simd package, built with the GOEXPERIMENT=simd flag. The same code compiles to AVX/AVX2/AVX512 on amd64, NEON on arm64, and SIMD128 on wasm, picking the widest vector the CPU supports at runtime, with an automatic fallback to the scalar lo.* implementation everywhere else (including GODEBUG=simd=0).
This documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please open an issue.
Your feedback helps us improve!
SIMD helpers are experimental. The API may break in the future.
Performanceโ
Benchmarks show that running SIMD operations on small datasets (below one vector's worth of data) is slower, since the fixed vector setup cost dominates:
BenchmarkSumInt8/small/lo-2 344053036 3.576 ns/op
BenchmarkSumInt8/small/simd-2 48484386 24.80 ns/op
But much faster on large datasets, where the win scales with the CPU's vector width (up to 16 int32 lanes on AVX-512, 4 on NEON):
BenchmarkSumInt8/xlarge/lo-2 466400 2576 ns/op
BenchmarkSumInt8/xlarge/simd-2 13143464 92.25 ns/op
See BENCHMARK.md for a full amd64 (AVX-512) vs arm64 (NEON) comparison across every helper.
Sumโ
Sums the values in a collection using SIMD instructions when available (AVX/AVX2/AVX512 on amd64, NEON on arm64, SIMD128 on wasm), falling back to a plain scalar loop everywhere else.
sum := simd.SumInt32([]int32{1000000, 2000000, 3000000})// 6000000sum := simd.SumFloat32([]float32{1.1, 2.2, 3.3, 4.4})// 11// Empty collection returns 0sum := simd.SumUint16([]uint16{})// 0Similar:Prototypes:func SumInt8[T ~int8](collection []T) Tfunc SumInt16[T ~int16](collection []T) Tfunc SumInt32[T ~int32](collection []T) Tfunc SumInt64[T ~int64](collection []T) Tfunc SumUint8[T ~uint8](collection []T) Tfunc SumUint16[T ~uint16](collection []T) Tfunc SumUint32[T ~uint32](collection []T) Tfunc SumUint64[T ~uint64](collection []T) Tfunc SumFloat32[T ~float32](collection []T) Tfunc SumFloat64[T ~float64](collection []T) TMeanโ
Calculates the arithmetic mean of a collection using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
mean := simd.MeanInt16([]int16{10, 20, 30, 40})// 25mean := simd.MeanFloat32([]float32{1.0, 2.0, 3.0, 4.0})// 2.5// Empty collection returns 0mean := simd.MeanUint32([]uint32{})// 0Similar:Prototypes:func MeanInt8[T ~int8](collection []T) Tfunc MeanInt16[T ~int16](collection []T) Tfunc MeanInt32[T ~int32](collection []T) Tfunc MeanInt64[T ~int64](collection []T) Tfunc MeanUint8[T ~uint8](collection []T) Tfunc MeanUint16[T ~uint16](collection []T) Tfunc MeanUint32[T ~uint32](collection []T) Tfunc MeanUint64[T ~uint64](collection []T) Tfunc MeanFloat32[T ~float32](collection []T) Tfunc MeanFloat64[T ~float64](collection []T) TMinโ
Finds the minimum value in a collection using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
min := simd.MinInt32([]int32{100, 50, 200, 75})// 50min := simd.MinFloat32([]float32{3.5, 1.2, 4.8, 2.1})// 1.2// Empty collection returns 0min := simd.MinUint16([]uint16{})// 0Prototypes:func MinInt8[T ~int8](collection []T) Tfunc MinInt16[T ~int16](collection []T) Tfunc MinInt32[T ~int32](collection []T) Tfunc MinInt64[T ~int64](collection []T) Tfunc MinUint8[T ~uint8](collection []T) Tfunc MinUint16[T ~uint16](collection []T) Tfunc MinUint32[T ~uint32](collection []T) Tfunc MinUint64[T ~uint64](collection []T) Tfunc MinFloat32[T ~float32](collection []T) Tfunc MinFloat64[T ~float64](collection []T) TMaxโ
Finds the maximum value in a collection using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
max := simd.MaxInt32([]int32{100, 50, 200, 75})// 200max := simd.MaxFloat32([]float32{3.5, 1.2, 4.8, 2.1})// 4.8// Empty collection returns 0max := simd.MaxUint16([]uint16{})// 0Prototypes:func MaxInt8[T ~int8](collection []T) Tfunc MaxInt16[T ~int16](collection []T) Tfunc MaxInt32[T ~int32](collection []T) Tfunc MaxInt64[T ~int64](collection []T) Tfunc MaxUint8[T ~uint8](collection []T) Tfunc MaxUint16[T ~uint16](collection []T) Tfunc MaxUint32[T ~uint32](collection []T) Tfunc MaxUint64[T ~uint64](collection []T) Tfunc MaxFloat32[T ~float32](collection []T) Tfunc MaxFloat64[T ~float64](collection []T) TClampโ
Clamps each element in a collection between mn and mx using SIMD instructions when available, falling back to a plain scalar loop everywhere else. If mn > mx, every element clamps to mn.
result := simd.ClampInt8([]int8{1, 5, 10, 15, 20}, 5, 15)// []int8{5, 5, 10, 15, 15}result := simd.ClampFloat32([]float32{0.5, 1.5, 2.5, 3.5}, 1.0, 3.0)// []float32{1.0, 1.5, 2.5, 3.0}// Empty collection returns an empty collectionresult := simd.ClampUint32([]uint32{}, 10, 100)// []uint32{}Prototypes:func ClampInt8[T ~int8, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampInt16[T ~int16, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampInt32[T ~int32, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampInt64[T ~int64, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampUint8[T ~uint8, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampUint16[T ~uint16, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampUint32[T ~uint32, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampUint64[T ~uint64, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampFloat32[T ~float32, Slice ~[]T](collection Slice, mn, mx T) Slicefunc ClampFloat64[T ~float64, Slice ~[]T](collection Slice, mn, mx T) SliceSumByโ
Transforms a collection using an iteratee function and sums the result using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
type Person struct {Name stringAge int8}people := []Person{{Name: "Alice", Age: 25},{Name: "Bob", Age: 30},{Name: "Charlie", Age: 35},}sum := simd.SumByInt8(people, func(p Person) int8 {return p.Age})// 90type Product struct {Name stringPrice float32Stock int32}products := []Product{{Name: "Widget", Price: 10.50, Stock: 5},{Name: "Gadget", Price: 20.00, Stock: 3},{Name: "Tool", Price: 15.75, Stock: 2},}sum := simd.SumByFloat32(products, func(p Product) float32 {return p.Price * float32(p.Stock)})// 152.5// Empty collection returns 0type Item struct {Count int64}sum := simd.SumByInt64([]Item{}, func(i Item) int64 {return i.Count})// 0Prototypes:func SumByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) Rfunc SumByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) Rfunc SumByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) Rfunc SumByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) Rfunc SumByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) Rfunc SumByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) Rfunc SumByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) Rfunc SumByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) Rfunc SumByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) Rfunc SumByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) RMeanByโ
Transforms a collection using an iteratee function and calculates the arithmetic mean of the result using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
type Person struct {Name stringAge int8}people := []Person{{Name: "Alice", Age: 20},{Name: "Bob", Age: 30},{Name: "Charlie", Age: 40},}mean := simd.MeanByInt8(people, func(p Person) int8 {return p.Age})// 30type Product struct {Name stringPrice float32}products := []Product{{Name: "Widget", Price: 10.50},{Name: "Gadget", Price: 20.00},{Name: "Tool", Price: 15.75},}mean := simd.MeanByFloat32(products, func(p Product) float32 {return p.Price})// 15.4167// Empty collection returns 0type Item struct {Count int64}mean := simd.MeanByInt64([]Item{}, func(i Item) int64 {return i.Count})// 0Prototypes:func MeanByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) Rfunc MeanByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) Rfunc MeanByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) Rfunc MeanByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) Rfunc MeanByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) Rfunc MeanByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) Rfunc MeanByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) Rfunc MeanByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) Rfunc MeanByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) Rfunc MeanByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) RContainsโ
Checks if a target value is present in a collection using SIMD instructions when available, falling back to a plain scalar loop everywhere else.
found := simd.ContainsInt32([]int32{1, 2, 3, 4, 5}, 3)// truefound := simd.ContainsFloat32([]float32{1.1, 2.2, 3.3, 4.4}, 3.3)// true// Empty collection returns falsefound := simd.ContainsInt16([]int16{}, 5)// falsePrototypes:func ContainsInt8[T ~int8](collection []T, target T) boolfunc ContainsInt16[T ~int16](collection []T, target T) boolfunc ContainsInt32[T ~int32](collection []T, target T) boolfunc ContainsInt64[T ~int64](collection []T, target T) boolfunc ContainsUint8[T ~uint8](collection []T, target T) boolfunc ContainsUint16[T ~uint16](collection []T, target T) boolfunc ContainsUint32[T ~uint32](collection []T, target T) boolfunc ContainsUint64[T ~uint64](collection []T, target T) boolfunc ContainsFloat32[T ~float32](collection []T, target T) boolfunc ContainsFloat64[T ~float64](collection []T, target T) bool