Skip to content

perf: LASX kernels on loong64 (sum, dot, sqrt, elementwise, 8x8 GEMM) - #22

Merged
tannevaled merged 2 commits into
mainfrom
perf/loong64-lasx
Oct 4, 2026
Merged

tannevaled merged 2 commits into
mainfrom
perf/loong64-lasx

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Go's loong64 assembler has LASX float64 add/sub/mul/div, sqrt and 256-bit
loads, but no fused multiply-add and no broadcast load; go-asmgen v0.14.0
encodes xvfmadd.d and xvldrepl.d (transitionally, until cmd/asm names
them). This uses them for sum, dot, sqrt, add/sub/mul/div and an 8x8 GEMM
micro-kernel (sum_loong64.s, generated). LASX is not on every LoongArch
CPU: the kernels run only when AT_HWCAP reports it, read from
/proc/self/auxv by a pure function (hwcap.go) that is tested on every
target; otherwise the scalar code runs, including a scalar 8x8 tile.

Loongson 3C5000L (cfarm401; its load average of ~146 is processes stuck
in uninterruptible sleep, the CPUs measured 100% idle), against the scalar
code, best of 3 interleaved runs:
micro-kernel 7.0 -> 27.5 GFLOP/s; serial GEMM 512^2 5.3 -> 20.0
MatMul x1.1-1.9 (32 threads); Sum one core x10.2 at 256 Ki, x2.5 at 4 Mi
Sqrt x3.8 below 16 Ki; MatVec x1.6; memory-bound 4 Mi cases at parity

Tests: the whole suite passes on the 3C5000L, and again with LASX forced
off. A wrong scalar-FMA operand order in the dot tail (Go's FMADDD is Fa,
Fk, Fj, Fd) failed the dot tests there before the fix; broadcasting the
wrong A rows fails the GEMM tests. CI regenerates sum_loong64.s and fails
if it is stale. Docs and comments that said loong64 has no SIMD kernel are
updated, and a comment claiming the scalar targets beat NumPy (never
measured) is removed.

🤖 Generated with Claude Code

tannevaled and others added 2 commits October 4, 2026 19:04
Go's loong64 assembler has LASX float64 add/sub/mul/div, sqrt and 256-bit
loads, but no fused multiply-add and no broadcast load; go-asmgen v0.14.0
encodes xvfmadd.d and xvldrepl.d (transitionally, until cmd/asm names
them). This uses them for sum, dot, sqrt, add/sub/mul/div and an 8x8 GEMM
micro-kernel (sum_loong64.s, generated). LASX is not on every LoongArch
CPU: the kernels run only when AT_HWCAP reports it, read from
/proc/self/auxv by a pure function (hwcap.go) that is tested on every
target; otherwise the scalar code runs, including a scalar 8x8 tile.

Loongson 3C5000L (cfarm401; its load average of ~146 is processes stuck
in uninterruptible sleep, the CPUs measured 100% idle), against the scalar
code, best of 3 interleaved runs:
  micro-kernel 7.0 -> 27.5 GFLOP/s; serial GEMM 512^2 5.3 -> 20.0
  MatMul x1.1-1.9 (32 threads); Sum one core x10.2 at 256 Ki, x2.5 at 4 Mi
  Sqrt x3.8 below 16 Ki; MatVec x1.6; memory-bound 4 Mi cases at parity

Tests: the whole suite passes on the 3C5000L, and again with LASX forced
off. A wrong scalar-FMA operand order in the dot tail (Go's FMADDD is Fa,
Fk, Fj, Fd) failed the dot tests there before the fix; broadcasting the
wrong A rows fails the GEMM tests. CI regenerates sum_loong64.s and fails
if it is stale. Docs and comments that said loong64 has no SIMD kernel are
updated, and a comment claiming the scalar targets beat NumPy (never
measured) is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit eafda19 into main Oct 4, 2026
12 checks passed
@tannevaled
tannevaled deleted the perf/loong64-lasx branch October 4, 2026 17:20
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