Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describes**:

| Source | Published under |
| --- | --- |
| branch `main`, with `params.ndarray.version: v0.13.0` in `hugo.yaml` | `https://go-ndarray.github.io/docs/<MAJOR.MINOR>/`, here `/docs/0.13/` |
| branch `main`, with `params.ndarray.version: v0.14.0` in `hugo.yaml` | `https://go-ndarray.github.io/docs/<MAJOR.MINOR>/`, here `/docs/0.14/` |
| the newest version | also `https://go-ndarray.github.io/docs/latest/` |

`https://go-ndarray.github.io/docs/` redirects to `latest/`. Each push to
Expand Down
2 changes: 1 addition & 1 deletion content/en/dtypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "Why the dtype is a run-time property of one Array type, how arrays
tags: [dtypes, numpy]
---

> Mirrored from [`docs/design-dtypes.md`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/docs/design-dtypes.md) at v0.13.0.
> Mirrored from [`docs/design-dtypes.md`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/docs/design-dtypes.md) at v0.14.0.

> Status: implemented (Phase 2). Supersedes decision 4 of
> [plan-ndarray.md](roadmap.md) ("`float64` first").
Expand Down
4 changes: 2 additions & 2 deletions content/en/linalg.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ description: "Solve, Inv, Det, Cholesky, QR, SVD, Eig and the rest of numpy.lina
tags: [linalg, numpy]
---

> Mirrored from [`docs/linalg.md`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/docs/linalg.md) at v0.13.0.
> Mirrored from [`docs/linalg.md`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/docs/linalg.md) at v0.14.0.

Package [`linalg`](https://pkg.go.dev/github.com/go-ndarray/ndarray@v0.13.0/linalg) gives ndarray arrays the functions of
Package [`linalg`](https://pkg.go.dev/github.com/go-ndarray/ndarray@v0.14.0/linalg) gives ndarray arrays the functions of
`numpy.linalg`, written in Go without cgo or assembly of its own: the
matrix products it relies on are the ndarray package's packed SIMD GEMM.

Expand Down
57 changes: 54 additions & 3 deletions content/en/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -880,9 +880,60 @@ float32 sum is also more accurate: on 2¹⁶ values of mixed sign and magnitude
its error against the exact sum (`math/big`) fell from 75 to 0.87, and 2²⁴
followed by 1000 ones no longer saturates at 2²⁴ (`sum_pairwise_test.go`).

Left: float32 has no SIMD kernel yet (still 7× float64 for `Sum`), and the
integer sums convert the whole array to int64 before adding (NumPy's
accumulator type), an extra pass and allocation.
The narrow integer sums still converted the whole array to int64 (NumPy's
accumulator) before adding: an extra pass and 8 bytes an element. Since
v0.14.0 a sum or product of bools or integers narrower than 64 bits along a
contiguous axis widens each element as it is read (`foldWidened`, same
arithmetic, wrap-around included): **int32 `Sum` of 2²⁰ elements 2.872 →
1.548 ms (−46%)**, 2¹⁴ −51%, with float64, float32 and int64 unchanged as
controls (POWER9, same protocol, p = 0.002).

### float32 sums on SSE2 and NEON (2026-10-18)

NumPy keeps eight accumulators in its pairwise sum so that the inner loop can
be vectorised "without changing summation ordering". `kernels.AddBlocks8F32`
is that loop: blocks of eight float32 added lane by lane, one IEEE addition
per lane per block, in order. It is SSE2 on amd64 (`ADDPS` on two XMM
registers) and NEON on arm64 (`VFADD` on two `.S4` registers), and the scalar
loop elsewhere, so float32 sums are unchanged bit for bit. The kernel is
tested bit for bit against the scalar loop (NaN, the infinities, −0,
subnormals, overflow), and fenced with `PROT_NONE` pages on both operands. A
kernel adding from the wrong register fails the first test, and one reading
a block too many faults in the fence.

Measured twice. First with the `bench` workflow on the hosted runners
(base and head alternated ten times in fresh processes on one thread,
`benchstat`, p ≤ 0.002), because the development Mac ran at a load of 97 and
most cfarm hosts refuse their keys since the host CA was revoked. Then on
real, idle hardware reached through a known_hosts file whose keys were
confirmed over a second network path: cfarm424 (Neoverse N1, 0.0% busy) and
cfarm420 (Zen 3, EPYC 7773X, 1.7% busy), same protocol, pinned to the idlest
CPU. On those, float32 `Sum` was −39% / −32% (N1) and −43% / −41% (Zen 3) at
2¹⁴ / 2²⁰. int32 was −15% / −11% on the N1, and on the Zen 3 within the
noise (±10% at that host's variance). The controls were unchanged.

| vs v0.13.x | amd64 (EPYC 9V45) | arm64 (hosted) |
|---|---:|---:|
| float32 `Sum`, 2¹⁴ | −50% | −33% |
| float32 `Sum`, 2²⁰ | −49% | −43% |
| int32 `Sum`, 2¹⁴ | −12% | −12% |
| int32 `Sum`, 2²⁰ | −15% | −13% |
| float64, int64 `Sum` (controls) | ~ | ~ |

The integer rows come from a defect the first run exposed. With the kernel
added, int32 `Sum` was **48–56% slower on amd64** although its code had not
changed: the disassembly of both binaries showed the same loop, byte for
byte, moved 224 bytes and now straddling a 64-byte line. The loop also
reloaded the operation from the stack every element. The widening folds now
use one loop per operation and four accumulators (exact: integer addition
and multiplication wrap modulo 2⁶⁴, so the order changes nothing). They also
consume the slice instead of indexing `i+1…i+3`, which had left four bounds
checks per iteration in the amd64 code; now there are none.

Left: ppc64le, s390x, loong64 and riscv64 run the scalar block loop. ppc64le
needs `xvaddsp`, which Go's assembler lacks: go-asmgen/asmgen#27 adds the
VSX single-precision family to its registry, with references from GNU as
and llvm-mc.

## SIMD coverage

Expand Down
8 changes: 4 additions & 4 deletions content/en/random.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ description: "numpy.random with NumPy's numbers for the same seed: the bit gener
tags: [random, numpy]
---

> Mirrored from [`docs/random.md`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/docs/random.md) at v0.13.0.
> Mirrored from [`docs/random.md`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/docs/random.md) at v0.14.0.

Package [`random`](https://pkg.go.dev/github.com/go-ndarray/ndarray@v0.13.0/random) is `numpy.random` over go-ndarray arrays. Its goal
Package [`random`](https://pkg.go.dev/github.com/go-ndarray/ndarray@v0.14.0/random) is `numpy.random` over go-ndarray arrays. Its goal
is migration: a notebook moved from NumPy to Go keeps its numbers for the same
seed.

Expand All @@ -24,7 +24,7 @@ u, _ := random.Rand(3) // np.random.rand(3)
```

`Example`, `ExampleSeed` and `ExampleGenerator_ChoiceN` in
[`example_test.go`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/random/example_test.go) print NumPy's own numbers.
[`example_test.go`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/random/example_test.go) print NumPy's own numbers.

## What is implemented

Expand Down Expand Up @@ -118,7 +118,7 @@ random arguments. Used as-is, that made 3% of `np.random.randn` values and
10% of `lognormal` values one ULP off.

So `random` rounds `log`, `log1p`, `exp`, `expm1` and `pow` **correctly**
([`libm.go`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/random/libm.go)): a fast evaluation to about 2⁻⁶⁸ with Ziv's
([`libm.go`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/random/libm.go)): a fast evaluation to about 2⁻⁶⁸ with Ziv's
rounding test, and a double-double fallback (about 2⁻¹⁰⁰) for the one argument
in ~2¹⁵ that needs it. Checked against mpmath at 300 bits on 63,000 arguments
(0 misrounded; the committed `libm.json` keeps 8,400), and the fast paths
Expand Down
4 changes: 2 additions & 2 deletions content/en/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "The plan for go-ndarray and what ships today."
tags: [roadmap]
---

> Mirrored from [`docs/plan-ndarray.md`](https://github.com/go-ndarray/ndarray/blob/v0.13.0/docs/plan-ndarray.md) at v0.13.0.
> Mirrored from [`docs/plan-ndarray.md`](https://github.com/go-ndarray/ndarray/blob/v0.14.0/docs/plan-ndarray.md) at v0.14.0.

> Goal: a **pure-Go (CGO=0)** NumPy-style N-dimensional array library, as a
> **standalone, reusable** module with correct scalar kernels now and a clean
Expand Down Expand Up @@ -112,7 +112,7 @@ suite (plus the per-arch CI jobs already wired in `.github/workflows/ci.yml`).
- **Performance — DONE (beats NumPy on its core ops; matmul at tuned-BLAS
parity).** Several levers behind the kernel seam, measured honestly vs NumPy
2.2.4 (see [docs/perf.md](performance.md) and the repo's
[BENCHMARKS.md](https://github.com/go-ndarray/ndarray/blob/v0.13.0/BENCHMARKS.md)):
[BENCHMARKS.md](https://github.com/go-ndarray/ndarray/blob/v0.14.0/BENCHMARKS.md)):
- **Multicore.** `Add/Sub/Mul/Div/Map`, `Sum/Max/Min`, the axis reductions,
`Concatenate`/`Stack`, and the GEMM fan out across `GOMAXPROCS` above a size
threshold (small arrays stay serial). Plus an allocation fix: the
Expand Down
2 changes: 1 addition & 1 deletion content/en/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "How to report a vulnerability, what the library guarantees, and th
tags: [security]
---

> Mirrored from [`SECURITY.md`](https://github.com/go-ndarray/ndarray/blob/main/SECURITY.md) at v0.13.0.
> Mirrored from [`SECURITY.md`](https://github.com/go-ndarray/ndarray/blob/main/SECURITY.md) at v0.14.0.

## Reporting

Expand Down
4 changes: 2 additions & 2 deletions hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# have used since the site was built with MkDocs and mike. The CI sets it
# through --baseURL, from params.ndarray.version below. This default is the
# same build.
baseURL: "https://go-ndarray.github.io/docs/0.13/"
baseURL: "https://go-ndarray.github.io/docs/0.14/"
title: "go-ndarray"
# themes/hextra is the tannevaled/hextra fork, pinned at a release tag:
# upstream Hextra plus opt-in features (partial menu items, combos,
Expand Down Expand Up @@ -97,7 +97,7 @@ params:
# The ndarray release these pages describe. Its minor version is the
# documentation's version label (v0.9.1 -> 0.9): the CI reads it here.
ndarray:
version: "v0.13.0"
version: "v0.14.0"

navbar:
displayTitle: true
Expand Down
Loading