Repository navigation
perf: float32 pairwise sum blocks on RVV (riscv64) and LSX (loong64) - #55
Merged
Merged
Conversation
AddBlocks8F32 gains two kernels, each behind the feature bit the float64 kernels already use (useRVV, useLASX), the scalar loop otherwise: - riscv64: VSETIVLI $8, E32, M2 gives vl = 8 on every VLEN >= 128; the eight accumulators in the group V2-V3, VFADDVV per block. - loong64: the eight accumulators fill one 256-bit register, XVADDF (xvfadd.s) per block. One IEEE float32 addition per lane per block, in order: float32 sums are unchanged bit for bit. Both are spelled by Go's own assembler. Run on real hardware: the kernel tests (bit-identity, refusals, fence) and the float32 sum tests pass on cfarm95 (SpacemiT X60, RVV, VLEN 256) and cfarm401 (Loongson, LASX); a sabotaged kernel fails the bit-identity test on both, so the kernel path is the one taken there. All seven targets build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne LASX The 256-bit version kept the eight accumulators in one register, a single dependency chain, and was 26-47% slower than the scalar loop on a Loongson 3C5000L. Two 128-bit registers, two chains: -24% at 2^14 and 2^20 there, bit-identity test passing on the hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 3C5000L Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AddBlocks8F32, the inner block of NumPy's pairwise sum, gains two kernels. Each runs behind the feature bit its float64 kernels already use (useRVV,useLASX), and the scalar loop runs otherwise. Both are spelled by Go's own assembler.VSETIVLI $8, E32, M2gives vl = 8 on every VLEN ≥ 128, the V extension's minimum. The eight accumulators sit in the group V2–V3, with oneVFADDVVper block.VADDF(vfadd.s) per register per block.There is one IEEE float32 addition per lane per block, in order, so float32 sums are unchanged bit for bit.
Run on the real hardware:
PROT_NONEfence) and the float32 sum tests pass on cfarm95 (SpacemiT X60, RVV, VLEN 256) and cfarm401 (Loongson 3C5000L).Measured with old and new binaries alternating 6 times, one pinned thread,
benchstatp = 0.002:Sum, 2¹⁴ / 2²⁰A first loong64 version lost, and was dropped. One 256-bit LASX register for all eight accumulators came out 26–47% slower than the scalar loop on the 3C5000L, with the host 0% busy. Every block's addition waited on the previous one: a single dependency chain, where the scalar loop has eight. Two LSX registers give two chains, as SSE2 does on amd64, and that version wins.
Left: ppc64le and s390x. Go's assembler lacks
xvaddspandvfasb; go-asmgen/asmgen#27 is the start.🤖 Generated with Claude Code