Commit 5b9c0f5
feat(native-cpu): cross-arch CI matrix + MSVC/Clang portability (PR 4 of 5)
PR 4 of the staged native-FFM rollout per docs/.../perf/native-ffm-plan.adoc.
The local Gradle build still produces only the host-arch shared
library, but cross-arch coverage now ships via CI: every push and PR
that touches the native module builds and runs jvmTest on
linux-x86_64, linux-arm64, macos-arm64, and windows-x86_64 in
parallel. This catches portability regressions (linker, alignment,
compiler-specific syntax) at PR time instead of letting them silently
ship to consumers on non-x86_64 hosts.
CI workflow (.github/workflows/native-cpu-multiarch.yml):
- Matrix of 4 hosts: ubuntu-latest, ubuntu-24.04-arm, macos-14
(Apple Silicon), windows-latest.
- Each runner: setup-java JDK 25 zulu, cmake --version sanity, then
./gradlew :skainet-backends:skainet-backend-native-cpu:jvmTest +
jvmJar. Drives the full CMake configure → build → bundle → FFM
downcall test pipeline.
- Path-filtered triggers — only runs when the native module, the
jvmMain part of skainet-backend-api (where the MemSeg SPI lives),
or this workflow file changes. Keeps unrelated CI noise low.
- fail-fast: false so one arch failure doesn't cancel the others.
- Uploads each arch's libskainet_kernels.{so,dylib,dll} as a named
artifact (libskainet_kernels-<arch_label>) plus per-arch test
reports for triage. The artifacts are the input a future "fat-JAR"
aggregation step will combine into a single multi-arch publishable
JAR (deferred to a follow-up; see Out of scope).
C portability fixes (native/):
- skainet_kernels.h adds a SKAINET_RESTRICT macro: __restrict__ on
GCC/Clang, __restrict on MSVC, empty otherwise. q4k_matmul.c
switches from raw __restrict__ to the macro so the Windows MSVC
build no longer rejects the function signatures.
- CMakeLists.txt grows an MSVC branch alongside the existing
GCC/Clang one: /O2 /fp:fast /W3 (analogues of -O3 -ffast-math
-Wall). Visibility on Windows is handled by the existing
SKAINET_API __declspec(dllexport) macro; no additional flags
needed. The Copy task in build.gradle.kts already includes both
flat (skainet_kernels.dll) and Visual Studio multi-config
(Release/skainet_kernels.dll) layouts, so the bundling step
works regardless of generator.
What is NOT in this PR (intentional):
- Hand-written AVX2 / NEON intrinsics. The current scalar C kernel
under -O3 -ffast-math is already 4.17–5.87× faster than Panama
Vector at LLM-typical Q4_K shapes (PR 2 numbers); GCC and Clang
auto-vectorize the 32-iteration inner loop into AVX2 / NEON
fmla / vfmadd213ps already. Hand-tuned intrinsics would just match
what the compiler emits. Adding them is busywork until a profile
shows a specific kernel where the compiler is leaving FLOPs on
the table.
- Multi-threading. Native is single-threaded today; Panama uses
parallelChunks across all cores and still loses to scalar single-
threaded native at every measured shape (the parallelChunks
dispatch overhead dominates). A focused multi-threaded native
variant becomes worthwhile once a real workload's per-call time
exceeds a few ms; current Q4_K matmul at 4096² is ~6 ms single-
threaded.
- Maven Central native classifier publishing / fat-JAR aggregation.
The CI artifacts are downloadable per-arch but not yet bundled
into a single publishable JAR with all four .so/.dylib/.dll files.
That belongs in a separate plan with the publishing infrastructure
(vanniktech.mavenPublish hooks, signing, classifier strategy).
Verification (linux-x86_64 host, JDK 21.0.10, cmake 3.28.3, gcc 13.3):
- :skainet-backends:skainet-backend-native-cpu:jvmTest — 17/17 pass
after the SKAINET_RESTRICT swap (3 pipeline + 5 heap-parity +
7 memseg-parity + 1 microbench-gated + 1 incidental).
- The macOS, Linux ARM64, and Windows runners exercise everything
the local build doesn't. CI status on this PR is the actual
cross-arch verification — locally I can't prove macos-arm64 or
windows-x86_64 work without those hosts.
Out of scope (deferred per asciidoc staging):
- PR 5: native FP32 / Q6_K / Q8_0 kernels (one PR per format,
template lifted from PR 2).
- Maven Central native classifier publishing + fat-JAR aggregation.
- AVX2 / NEON intrinsic kernels, multi-threading, prefetch tuning.
- Build instructions for users who want to cross-compile all arches
locally (currently CI is the path to a multi-arch artifact).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 33a576c commit 5b9c0f5
4 files changed
Lines changed: 142 additions & 5 deletions
File tree
- .github/workflows
- skainet-backends/skainet-backend-native-cpu/native
- include
- src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
Lines changed: 11 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
29 | 32 | | |
30 | 33 | | |
31 | 34 | | |
| |||
35 | 38 | | |
36 | 39 | | |
37 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
38 | 47 | | |
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
14 | 25 | | |
15 | 26 | | |
16 | 27 | | |
| |||
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
| 79 | + | |
80 | 80 | | |
81 | | - | |
| 81 | + | |
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| |||
0 commit comments