Repository navigation
NEON kernels for the correctly rounded float32 Exp and Log - #95
Closed
tannevaled wants to merge 2 commits into
Closed
tannevaled wants to merge 2 commits into
tannevaled wants to merge 2 commits into
Conversation
exp32CRNEON runs expCR (Arm's cr_expf, an AdvSIMD routine to begin with) on eight float32 per iteration: FCVTL/FCVTL2 widen, VFMLA/VFMLS do expCR's fused operations in its order, the table is read through two general registers per pair, FCVTN/FCVTN2 round once. A block with a lane outside [-512, 512] or a NaN (FACGE) is handed back to exp32CR before anything is stored. FCVTL/FCVTN/FACGE are emitted as WORDs; go tool objdump decodes each as intended. TestExp32NEONMatchesGo holds it to exp32CR bit for bit (random bits, a dense range, specials, lengths 0..70, in place); widening the wrong half (FCVTL for FCVTL2) fails it and the exhaustive sample (1602 wrong of 65536). Fenced; the constant block's layout is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
log32CRNEON runs logCR's fast path (CORE-MATH's logf) on eight float32 per iteration, the twin of log32CRAVX2: m, j, e, x == 1 and the positive-normal test in 32-bit lanes; per pair, tz (UXTL), e (SXTL, SCVTF), tr[j] and tl[j] through general registers, logCR's unfused VFMUL/VFADD in its order, and both bounds rounded once (FCVTN/FCVTN2). A block with a lane that is not a positive normal, or whose bounds round apart, is handed back to logCR before anything is stored. UXTL, SXTL, SCVTF, CMGT and BIC are WORDs; go tool objdump decodes each as intended. Proof on darwin/arm64 over all 2^32 inputs: TestLog32CorrectlyRounded and TestExp32CorrectlyRounded, which now run the NEON kernels, find 0 incorrectly rounded. Dropping the positive-normal BIC fails TestLog32NEONMatchesGo (log(0) = -88.03) and the exhaustive sample (33016 wrong of 65536). Fenced; the constant block's layout is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
On hold, not to be merged here. ndarray's 1-D kernels are moving into go-simd/floats (go-scikit performance campaign, kernel K1), so there is one implementation. These NEON kernels go there with the AVX2 ones already on main ( The port keeps:
This PR stays open until the go-simd/floats PR is merged, then it will be closed with a pointer to it. 🤖 Generated with Claude Code |
Contributor
Author
|
Superseded by go-simd/floats#29 (merged 2026-11-07). These NEON kernels now live in go-simd/floats as 🤖 Generated with Claude Code |
tannevaled
added a commit
that referenced
this pull request
Nov 7, 2026
…xp, log (K1) (#97) * kernels: import go-simd/floats for sum, elementwise, extrema, clip, exp, log (K1) K1 of the go-scikit performance campaign (go-scikit/roadmap#27): ndarray now imports go-simd/floats v0.9.0 and deletes its copies. - exp, log, and the correctly rounded float32 exp/log (with the AVX2 kernels of #94/#96 and the NEON kernel of #95, now go-simd/floats#29): deleted here (Go sources, tests, generator kernels, assembly); Exp, Log, Exp32, Log32 and their P forms call floats. - amd64 and arm64: the sum/sqrt/max/min/add/sub/mul/div kernels are floats'; Clip is floats.ClampScalar. Max/Min resolve a zero result with the serial oracle (floats leaves the sign of zero unspecified). - Sum is floats.SumPairwise on every architecture: NumPy's order, bit-identical to np.sum; serial at every size. A changed last bit is the fix; the golden values of TestSumMatchesNumPy are NumPy 2.5.4's. - Not moved: the float32 elementwise/sqrt/extremum/AddBlocks8F32 kernels, the dot inside GEMM/Dot1D, and the ppc64le, loong64, riscv64 and s390x kernels (floats has none for them yet). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * kernels: test the parallel exp/log forms and Log10 (100% coverage gate) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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.
NEON kernels for the correctly rounded float32
ExpandLogon arm64, which until now ran the Go transcriptions.exp32CRNEONports Arm'scr_expf, an AdvSIMD routine to begin with, on 8 floats per iteration.expCR's fused operations in its order.cr_expfdoes, because NEON has no gather. FCVTN/FCVTN2 round once.exp32CRbefore anything is stored.log32CRNEONis the twin oflog32CRAVX2, runninglogCR's fast path (CORE-MATH's logf).m,j,e,x == 1, and the positive-normal test.tz(UXTL),e(SXTL, SCVTF),tr[j]andtl[j]through general registers, thenlogCR's unfused VFMUL/VFADD in its order. Both bounds are rounded once.logCR.Instructions Go's assembler does not name (FCVTL/FCVTN and their
2forms, FACGE, UXTL, SXTL, SCVTF, CMGT, BIC) are emitted as WORDs.go tool objdumpdecodes each one as intended, with operands in the right roles.Proof on darwin/arm64 over all 2³² inputs:
TestExp32CorrectlyRoundedandTestLog32CorrectlyRoundednow run the NEON kernels. Both find 0 incorrectly rounded, andlogCRequals the independent oracle everywhere.The tests catch planted defects:
TestExp32NEONMatchesGoand the exhaustive sample (1602 wrong of 65536).TestLog32NEONMatchesGo(log(0)= −88.03) and the sample (33016 wrong).Both kernels are bit-identical to the Go path on 300 000 inputs, every length 0–70 and in place, and both are fenced. Their constant blocks' layouts are tested.
⚠ Not yet measured. The arm64 hosts are loaded: this Mac is at load 78–103 and cfarm424 at 48 on 64 cores. A gated
abbench(v0.35.0 vs this branch, load ≤ 8) is queued. This PR will not be merged before its numbers are in and indocs/perf.md.Also: s390x (IBM z17) is now proven for float32
ExpandLogover all 2³² inputs (0 incorrectly rounded). That completes the set of 64-bit architectures.docs/perf.mdwill record it with the numbers.🤖 Generated with Claude Code