From b425569cb6d0336ed2737b0e39d1c012a54d4c12 Mon Sep 17 00:00:00 2001 From: michalharakal Date: Sun, 25 Oct 2026 19:43:33 +0100 Subject: [PATCH] release: 0.62.4 --- CHANGELOG.md | 11 +++++++++ CITATION.cff | 2 +- README.md | 23 ++++++++++++++++--- docs/antora.yml | 2 +- .../reference/kernel-support-matrix.adoc | 2 +- .../reference/operators/generated/index.adoc | 2 +- .../pages/reference/ops-status-matrix.adoc | 2 +- .../android-classifier-getting-started.adoc | 12 +++++----- gradle.properties | 2 +- 9 files changed, 43 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e587ae..07becff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## [Unreleased] +## [0.62.4] - 2026-10-25 + +Headline: **the arm64 release — the JVM on macOS sends its dense FP32 products to Accelerate, and the native dense +FP32 kernels get register tiles on AArch64** (#1449, #1450, see *Changed*). `JvmBlas` never reached a BLAS (framework +looked up by its bare name, heap arrays passed to a downcall, both failures swallowed); it now resolves `cblas_sgemm` +from `skainet.cpu.blas.library`, the Accelerate framework by path, or the common Linux sonames, and `A · B` on heap or +segment operands and `x · Wᵀ` on a resident dense weight go to it above a small-work floor, on by default on macOS +only. `skainet_fp32_matmul` on AArch64 runs an 8 × 8 tile of lane-indexed FMAs over a packed panel in a 256-deep +k-block and `skainet_fp32_matmul_wt` a four-by-three tile, bit-identical across slices and threads, verified on Apple +silicon by the macOS CI leg; no arm64 numbers were measured for this release. + ### Changed - **Dense FP32 kernels get register tiles on AArch64** (`skainet-backend-native-cpu`, Apple silicon, Android arm64, Linux arm64): the NEON bodies of `skainet_fp32_matmul` and `skainet_fp32_matmul_wt` were the x86 story of a week ago — an outer-product loop that loaded and stored a row of C for every row of A, and a single four-lane chain per `x · Wᵀ` output that left most of a core's FMA pipes idle. The plain SGEMM now runs an 8 × 8 tile in sixteen `float32x4` accumulators with lane-indexed FMAs over a packed 8-column panel of B in a 256-deep k-block (4 × 8 and 1 × 8 tiles for the rows left over, a zero-padded panel and C stripe for the columns left over), and `x · Wᵀ` a tile of four weight rows by three activation rows in twelve chains. Every output takes its fused steps in ascending `p` whichever tile holds it, so sliced, threaded and whole calls stay bit-identical to each other; against the previous NEON numbers an output moves within rounding. Two Kotlin/Native tests run the tails and the block independence through cinterop on every native target, so the macOS CI leg exercises the lane on Apple silicon. No numbers from this change's author: measured on an arm64 host it is not — see the pull request for how to run the bench. diff --git a/CITATION.cff b/CITATION.cff index 3c087979..2b90c15b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,7 +12,7 @@ authors: orcid: https://orcid.org/0009-0006-7981-4075 - name: SKaiNET-developers contributors website: https://github.com/SKaiNET-developers -version: "0.62.3" +version: "0.62.4" date-released: "2026-10-21" license: MIT repository-code: https://github.com/SKaiNET-developers/SKaiNET diff --git a/README.md b/README.md index 3d892c3f..b951d611 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Add the core dependencies (Gradle Kotlin DSL): ```kotlin dependencies { // Recommended: import the umbrella BOM and drop versions on the engine modules. - implementation(platform("sk.ainet:skainet-bom:0.62.3")) + implementation(platform("sk.ainet:skainet-bom:0.62.4")) implementation("sk.ainet.core:skainet-lang-core") implementation("sk.ainet.core:skainet-backend-cpu") @@ -308,7 +308,19 @@ val withoutLabel = dataPipeline() --- -## What's New in 0.62.3 +## What's New in 0.62.4 + +An arm64 release. On macOS the JVM's dense FP32 products — `A · B` on heap or segment-backed operands and `x · Wᵀ` +on a resident dense weight — now go to Accelerate's SGEMM by default, which runs on the matrix units of Apple +silicon and threads itself; `JvmBlas` had never reached a BLAS before (the framework lookup and the heap downcall +both failed silently), and `-Dskainet.cpu.blas.enabled=false` restores the bundled kernels. Elsewhere the default +stays off and `skainet.cpu.blas.library` names an OpenBLAS or reference BLAS to use. The native dense FP32 kernels +get register tiles on AArch64 (Apple silicon, Android arm64, Linux arm64): an 8 × 8 tile of lane-indexed FMAs over a +packed panel of B for `A · B` and a four-by-three tile for `x · Wᵀ`, bit-identical across slices, threads and whole +calls, exercised on Apple silicon by the macOS CI leg. Both are unmeasured on arm64 in this release; the pull +requests (#1449, #1450) say how to run the bench. + +### Carried from 0.62.3 A load-time and kernel release. `StreamingGGUFReader` decodes the GGUF metadata from 64 KB blocks instead of one source read per value, and `TextFrontEnds.fromGguf` builds a SentencePiece tokenizer in one pass over the vocabulary @@ -391,6 +403,11 @@ We love contributions! Whether it's a new operator, documentation, or a bug fix: Browse the full codebase documentation on [DeepWiki](https://deepwiki.com/SKaiNET-developers/SKaiNET). +### Contributors (0.62.4) + +- **Michal Harakal** ([@michalharakal](https://github.com/michalharakal)) — the Accelerate/BLAS routing of the JVM's + dense FP32 products, the AArch64 register tiles for the native dense FP32 kernels with their tests, and the release + ### Contributors (0.62.3) - **Michal Harakal** ([@michalharakal](https://github.com/michalharakal)) — the buffered GGUF metadata reader, the @@ -527,7 +544,7 @@ from it). Ready-to-paste BibTeX: author = {Harakal, Michal and {SKaiNET-developers contributors}}, title = {{SKaiNET}: A {Kotlin} Multiplatform {AI} Framework}, year = {2026}, - note = {Version 0.62.3. MIT License}, + note = {Version 0.62.4. MIT License}, howpublished = {\url{https://github.com/SKaiNET-developers/SKaiNET}} } ``` diff --git a/docs/antora.yml b/docs/antora.yml index c4a2d69a..43c8dcae 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -15,7 +15,7 @@ asciidoc: framework_name: SKaiNET # Current SKaiNET release — bump once per release; referenced as # {skainet_version} in dependency snippets (blocks need subs="attributes+"). - skainet_version: 0.62.3 + skainet_version: 0.62.4 ksp_version: 2.2.21-2.0.5 dokka_version: 2.1.0 asciidoctorj_version: 3.0.0 diff --git a/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc b/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc index 629f0102..56ca9f65 100644 --- a/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc +++ b/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc @@ -1,7 +1,7 @@ = Kernel × platform support matrix :description: Which compute-kernel provider serves each weight format on each KMP target. -Generated from `kernel-support.json` (version `0.62.3`) by `KernelSupportMatrixTest` — registry introspection of the registered `KernelProvider` implementations. Do not edit by hand; run `./gradlew generateKernelMatrix` to refresh. +Generated from `kernel-support.json` (version `0.62.4`) by `KernelSupportMatrixTest` — registry introspection of the registered `KernelProvider` implementations. Do not edit by hand; run `./gradlew generateKernelMatrix` to refresh. Each cell is the best (highest-priority) provider that serves `Float32 × format` `matmul` on that platform: *native-ffm* / *native-jni* / *native-cinterop* (100) → *panama-vector* / *wasm-simd128* (50) → *scalar* (0). An empty cell (`—`) means no provider carries a kernel there (the format is dequant-to-FP32 only). The JS/WASM column assumes `WasmSimd.install()` has run; without the sidecar it is the scalar floor. diff --git a/docs/modules/ROOT/pages/reference/operators/generated/index.adoc b/docs/modules/ROOT/pages/reference/operators/generated/index.adoc index c1c0e029..441bdbe3 100644 --- a/docs/modules/ROOT/pages/reference/operators/generated/index.adoc +++ b/docs/modules/ROOT/pages/reference/operators/generated/index.adoc @@ -1,6 +1,6 @@ = AI-NET Operators Reference -Generated from version `0.62.3` on 2026-10-25 +Generated from version `0.62.4` on 2026-10-25 == Operators by Modality diff --git a/docs/modules/ROOT/pages/reference/ops-status-matrix.adoc b/docs/modules/ROOT/pages/reference/ops-status-matrix.adoc index 4d3943fe..8638d49d 100644 --- a/docs/modules/ROOT/pages/reference/ops-status-matrix.adoc +++ b/docs/modules/ROOT/pages/reference/ops-status-matrix.adoc @@ -1,7 +1,7 @@ = Operator Coverage Matrix :description: Cross-backend status for every operator function in SKaiNET. -Generated from `operators.json` version `0.62.3` on 2026-10-25. +Generated from `operators.json` version `0.62.4` on 2026-10-25. Rows are `Operator.function` pairs. A gap is marked in source with `@NotImplemented(reason = …, issue = …)` (or `@InProgress`) and shows up here as ❌ (or 🚧) linked to its tracking issue; the PR that closes the gap removes the annotation. See xref:contributing/issue-taxonomy.adoc[Issue taxonomy] to pick one up. diff --git a/docs/modules/ROOT/pages/tutorials/android-classifier-getting-started.adoc b/docs/modules/ROOT/pages/tutorials/android-classifier-getting-started.adoc index 499ecc2f..6e98d3fc 100644 --- a/docs/modules/ROOT/pages/tutorials/android-classifier-getting-started.adoc +++ b/docs/modules/ROOT/pages/tutorials/android-classifier-getting-started.adoc @@ -19,12 +19,12 @@ An Android project with Kotlin. Add the SKaiNET modules: [source,kotlin] ---- dependencies { - implementation("sk.ainet.core:skainet-lang-core:0.62.3") // tensors, DSL, training - implementation("sk.ainet.core:skainet-backend-cpu:0.62.3") // CPU ops - implementation("sk.ainet.core:skainet-compile-dag:0.62.3") // autograd (training context) - implementation("sk.ainet.core:skainet-data-api:0.62.3") // Dataset / DataBatch - implementation("sk.ainet.core:skainet-data-simple:0.62.3") // embedded Iris - runtimeOnly("sk.ainet.core:skainet-backend-jni-cpu:0.62.3") // NEON kernels (see below) + implementation("sk.ainet.core:skainet-lang-core:0.62.4") // tensors, DSL, training + implementation("sk.ainet.core:skainet-backend-cpu:0.62.4") // CPU ops + implementation("sk.ainet.core:skainet-compile-dag:0.62.4") // autograd (training context) + implementation("sk.ainet.core:skainet-data-api:0.62.4") // Dataset / DataBatch + implementation("sk.ainet.core:skainet-data-simple:0.62.4") // embedded Iris + runtimeOnly("sk.ainet.core:skainet-backend-jni-cpu:0.62.4") // NEON kernels (see below) } ---- diff --git a/gradle.properties b/gradle.properties index 1b2cfc5e..1dd516ea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ GROUP=sk.ainet.core -VERSION_NAME=0.62.3 +VERSION_NAME=0.62.4 POM_DESCRIPTION=SKaiNET POM_URL=https://github.com/SKaiNET-developers/skainet/