Skip to content

Build Independently confirmed2 publishers 3 min read Published

Go 1.27 ships a size-agnostic simd package for loops that once needed per-architecture assembly

Go 1.27 adds an experimental, portable simd package covering AVX through AVX-512, Arm NEON and wasm SIMD instructions. The Go team's stated goal is near-assembly speed from code written once, and each fleet has to measure that on its own hardware.

The Engineer · Build desk

Send a correction

Illustration accompanying Go 1.27 ships a size-agnostic simd package for loops that once needed per-architecture assembly
Generated illustration

What happened

  • Before Go 1.26, the only way to use SIMD from Go was hand-written Go assembly, which the Go team says was only worth it for truly performance-critical kernels.
  • Go 1.26 added an amd64 SIMD API and Go 1.27 added arm64 NEON and wasm, all in an architecture-dependent package called archsimd.
  • The portable simd package is modeled on Highway, Google's SIMD library for C++.
  • The Go runtime already uses SIMD in its Green Tea garbage collector to speed up scanning memory for live objects.

Why it matters

  • Who has to decide decision Data and inference loops that never justified per-architecture assembly can now get a portable SIMD rewrite, and a benchmark on each target decides whether that rewrite stays.
  • What it costs cost Mixed amd64 and arm64 fleets need a benchmark run per architecture, because one source file executes with different lane counts on each.
  • Who's exposed exposure Teams shipping to riscv64, loong64, PowerPC or s390x get emulated vectors from the same source, so a portable kernel can reach those builds without anyone having measured a speedup there.

The obstacle to a single SIMD API in Go is the vector itself. On wasm, PowerPC and s390x a vector is 128 bits, amd64 offers 128, 256 and 512, and loong64 offers 128 and 256 [8]. Riscv64 allows any power of two from 128 to 65536 bits. Arm64 pairs fixed 128-bit NEON with SVE at 128 to 2048 bits [9]. On some platforms the size is unknown at build time and has to be queried when the program starts [10].

Masking is worse. Wasm, AVX, AVX2 and NEON have no mask registers, so masking is done with vector bitmasks and boolean operations [11]. AVX512 and RVV have mask registers with one bit per element [11]. SVE allocates one bit per vector byte and reads the least-significant bit of each element's group. AVX2's masked loads and stores take a plain vector and read the most-significant bit [12]. Wasm also has no comparison for vectors of 64-bit integers [13].

The archsimd package leaves many of those quirks visible. The Go team wrote that they make designing, writing and testing multiplatform SIMD code "onerous" [14]. After the masking rules, that word seems restrained. The team also wrote that archsimd could be made more uniform, "but we can only go so far without compromising efficiency" [14]. The portable simd package takes the other path and removes fixed-size vectors from the type system [15]. A kernel's types no longer commit it to 128 or 512 bits [15].

That portability changes what a benchmark number means. A 512-bit AVX-512 vector holds 8 float64 values, the post's own example of what one instruction can add. A 128-bit NEON vector holds 2 [20][18]. So the same source can process four times as many elements per instruction on one machine as on another [20]. An amd64 speedup carries over to arm64 only if the loop is limited by something other than vector width, such as memory bandwidth or a scalar tail.

Where the package has no hardware backend, it emulates vectors, and the post calls that emulation "competent" [7]. The supported list is AVX, AVX2 and AVX512 on amd64, NEON on arm64, and wasm's SIMD instructions [4]. Riscv64, loong64, PowerPC and s390x all appear in the post's own survey of SIMD architectures, and they run on emulation for now [21]. On arm64 the package uses NEON's fixed 128 bits, and SVE's wider vectors are not yet supported [4][9].

I think the two-package split is the right design. Archsimd keeps each platform's instructions reachable for the kernels that need a specific one, and simd covers the common loop [2][15]. For a service that runs on both amd64 and arm64, I would write the portable kernel first and benchmark it on each fleet. Assembly would stay only for a loop where the numbers show the portable version falls short.

What to watch

  • Whether Arm SVE support lands in Go 1.28, as Phoronix reports is planned, letting arm64 kernels use vectors wider than NEON's 128 bits.
  • Whether the Go team publishes measurements of the portable package against hand-written assembly, which would test the near-assembly goal.
  • Which operations are added before the package leaves experimental status, especially crypto primitives, which the Go post says differ from one architecture to the next.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence60
Adoption10
Hype gap+10
Incentives35
Confidence65
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    Go 1.26 and 1.27 include experimental APIs for SIMD operations.

    Reported SupportedView cited source
  2. [2]

    Go 1.26 introduced a SIMD API for amd64 and Go 1.27 added APIs for arm64 (NEON) and wasm; these live in an architecture-dependent archsimd package to give full access to each platform.

    Reported SupportedView cited source
  3. [3]

    Go 1.27 introduces an experimental, fully portable, platform- and size-agnostic SIMD interface loosely based on Highway for C++.

    Reported SupportedView cited source
  4. [4]

    The simd package currently supports AVX, AVX2, and AVX512 on amd64, NEON on arm64, and wasm's SIMD instructions.

    Reported SupportedView cited source
  5. [5]

    Go 1.27's portable, platform- and size-agnostic SIMD interface is modeled around Google's Highway library.

    Reported Supported Source: PhoronixView cited source
  6. [6]

    Before these experimental APIs, the only way to access SIMD from Go was writing Go assembly, which was only worth it for truly performance-critical compute kernels, so much software that could benefit from SIMD left CPU capability unused.

    Reported SupportedView cited source
  7. [7]

    The goal is to support write-once near-asm-performance simd code on platforms with SIMD support, and to provide a competent emulation on platforms that do not (yet) have SIMD support.

    Reported SupportedView cited source
  8. [8]

    Wasm, PowerPC and s390x provide a single fixed 128-bit vector size; amd64 provides 128, 256 and 512 bits; loong64 provides 128 and 256 bits.

    Reported SupportedView cited source
  9. [9]

    Riscv64 supports vectors of unspecified size between 128 and 65536 bits, powers of 2 only; arm64 supports one fixed size (128 bits, NEON) and one variable size (128-2048 bits, powers of two, SVE).

    Reported SupportedView cited source
  10. [10]

    On some platforms the vector size is not known at build time and must be queried when the program starts.

    Reported SupportedView cited source
  11. [11]

    Wasm, AVX, AVX2 and NEON do not provide masks, so masking is done with vector bitmasks and vector boolean operations; AVX512 and RVV provide special mask registers with one bit governing one vector element.

    Reported SupportedView cited source
  12. [12]

    SVE allocates one mask bit per vector byte, with the least-significant bit of each element's mask bits governing masked operations; AVX2 supports masked loads and stores using a plain vector as the mask, with the most-significant bit governing.

    Reported SupportedView cited source
  13. [13]

    Wasm lacks comparisons for vectors of 64-bit integers.

    Reported SupportedView cited source
  14. [14]

    The Go team wrote that remaining quirks in archsimd "make designing, writing, and testing code for multiplatform SIMD onerous" and that it could do more to make architectures appear similar, "but we can only go so far without compromising efficiency."

    Reported SupportedView cited source
  15. [15]

    The new simd package hides platform differences by removing fixed-size vectors from the type system.

    Reported SupportedView cited source
  16. [16]

    Go's Green Tea garbage collector uses SIMD to accelerate scanning memory for live objects.

    Reported SupportedView cited source
  17. [17]

    With Go 1.28, developers plan to add Arm SVE support to the SIMD code and to support more SIMD operations in the interface.

    Reported Supported Source: PhoronixView cited source
  18. [18]

    SIMD can, for example, add 8 pairs of float64 values in a single instruction.

    Reported SupportedView cited source
  19. [19]

    Different SIMD architectures support different crypto-related operations.

    Reported SupportedView cited source
  20. [20]

    A 512-bit AVX-512 vector holds 8 float64 values and a 128-bit NEON vector holds 2, a 4x difference in elements per instruction.

    Derived Supported
  21. [21]

    Riscv64, loong64, PowerPC and s390x are named in the Go post's survey of SIMD architectures but are absent from the simd package's supported list, so they fall under the package's emulation path for now.

    Derived Supported

Sources

2 independent publishers whose own reporting we read for this story.

  1. blog.golang.org

    1 article · September 23, 2026

    Platform-independent SIMD in Go
  2. phoronix.com

    1 article · September 25, 2026

    Go's Improving SIMD Support, Platform-Independent SIMD Interface

Topics and entities

Topics

  • SIMD programming
  • Programming language releases

Entities