Skip to content

feat(exp/simd): rewrite on go 1.27 portable simd package - #1005

Merged
samber merged 6 commits into
masterfrom
feat/exp-simd-portable
Sep 9, 2026
Merged

samber merged 6 commits into
masterfrom
feat/exp-simd-portable

Conversation

@samber

@samber samber commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace the go 1.26 simd/archsimd implementation (amd64-only, one hand-written kernel per instruction set, SIGILL hazard on CPUs without AVX2/AVX512) with go 1.27 portable stdlib simd package (amd64, arm64, wasm, plus a pure-Go emulated fallback everywhere else).
  • Split each operation into a non-generic kernel (kernel.go, the only file importing "simd") and a generic wrapper, avoiding the midway compiler pass generics limitations.
  • Min/Max/Clamp on float32/float64 now match lo.Min/lo.Max/lo.Clamp exactly on every architecture: NaN is detected cheaply and routed to the exact scalar algorithm instead of following architecture-dependent hardware NaN semantics; Clamp with mn > mx always returns mn on both the SIMD and scalar-fallback paths.
  • Raise the exp/simd minimum Go version to 1.27.
  • CI now tests go 1.26/1.27/stable on both amd64 and arm64 hardware, since the package is portable.
  • Update the docs site (source refs, trimmed per-type signatures, examples) for the new API surface.

Test plan

  • GOEXPERIMENT=simd go test -race ./... and GOEXPERIMENT=simd GODEBUG=simd=0 go test -race ./... (forced scalar fallback) both pass.
  • Cross-compiled for darwin/arm64, linux/amd64, linux/arm64, linux/riscv64, linux/386, js/wasm, windows/amd64, plus the no-experiment stub build.
  • golangci-lint run clean; -gcflags='-m' escape analysis confirms zero heap allocations in the hot kernels.

Go 1.26 simd/archsimd is amd64-only, with one hand-written kernel per
instruction set (AVX/AVX2/AVX512) and a SIGILL hazard on CPUs without
AVX2/AVX512. Go 1.27 ships a portable simd package (amd64, arm64, wasm,
plus a pure-Go emulated fallback), so the sub-module can support every
platform Go targets with a single set of kernels instead of three.

- Split each operation into a non-generic kernel (kernel.go, the only
  file importing "simd") and a generic wrapper, sidestepping the
  midway compiler pass generics limitations.
- Min/Max/Clamp on float32/float64 detect NaN cheaply and fall back to
  the exact scalar algorithm so SIMD and lo.Min/lo.Max/lo.Clamp always
  agree, instead of following architecture-dependent hardware NaN
  semantics.
- Clamp with mn > mx now always returns mn on both the SIMD and
  scalar-fallback paths (lo.Clamp itself is value-dependent for that
  malformed precondition, so no two-op composition can match it).

Raises the exp/simd minimum Go version to 1.27.
The simd package is portable, so exercise it across the minimum
supported compiler, the current stable release, and both amd64 and
arm64 hardware, instead of a single Go version on amd64 only.
The exp/simd docs described the old per-ISA archsimd API (AVX/AVX2/
AVX512 variants, CPU-flag detection). Update source references and
examples for the portable go 1.27 package, which picks the vector
width at runtime instead of exposing one function per width.
@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.87%. Comparing base (f728804) to head (c6f338e).
⚠️ Report is 23 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1005      +/-   ##
==========================================
+ Coverage   96.10%   98.87%   +2.77%     
==========================================
  Files          32       32              
  Lines        5520     4728     -792     
==========================================
- Hits         5305     4675     -630     
+ Misses        176       53     -123     
+ Partials       39        0      -39     
Flag Coverage Δ
unittests 98.87% <ø> (+2.77%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The old benchmark report described the archsimd implementation
(Fallback-lo/AVX-x16/AVX2-x32/AVX512-x64 sub-benchmarks, tiny/massive
size tiers) and had gone stale relative to the current code. Replace
it with a fresh amd64 (AVX-512) and arm64 (NEON) comparison, plus a
summary of how speedup scales with vector width across Sum/Min/Clamp/
Contains.
llms.txt never listed the exp/simd module, so LLM agents reading it
had no way to discover the SIMD helpers. The dedicated SIMD docs page
still described the old amd64-only, Go 1.26 AVX/AVX2/AVX512 implementation
and its retired per-ISA benchmark names; update it to match the go 1.27
portable rewrite and link to the regenerated BENCHMARK.md.
@samber
samber merged commit 0b1e6c5 into master Sep 9, 2026
23 of 25 checks passed
@samber
samber deleted the feat/exp-simd-portable branch September 9, 2026 10:10
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.

1 participant