Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

Open
vladimir-aubrecht wants to merge 5 commits into
dotnet:mainfrom
vladimir-aubrecht:feature/symsgd-arm64
Open

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 5 commits into
dotnet:mainfrom
vladimir-aubrecht:feature/symsgd-arm64

Conversation

@vladimir-aubrecht

Copy link
Copy Markdown
Contributor

Summary

Enables the SymbolicSgdLogisticRegression trainer (backed by SymSgdNative) on arm/arm64, where Intel MKL is unavailable. Fixes #5798.

SymSGD uses only four CBLAS routines (sdot, saxpy, sdoti, saxpyi). This PR provides them via a tiny, self-contained libMklImports shim built from portable C — with no external BLAS dependency — so it configures and links in the CI cross-compilation sysroots (which ship no OpenBLAS/BLAS).

Changes

  • src/Native/MklImportsArm/ (new): implements the four CBLAS routines as plain C loops (-O3 autovectorizes the dense paths to NEON) plus MKL DFTI stubs. No find_package(BLAS) — zero external deps. Symbols are exported explicitly because the native build uses -fvisibility=hidden.
  • src/Native/CMakeLists.txt: build MklImportsArm + SymSgdNative on arm.
  • src/Native/SymSgdNative/CMakeLists.txt: link SymSgdNative against the shim on arm.
  • src/Native/SymSgdNative/SparseBLAS.h: make the CBLAS calling convention portable (__cdecl only on _WIN32).
  • Directory.Build.targets: ship libMklImports and libSymSgdNative next to the managed assemblies on arm.
  • SymSgdClassificationTrainer.cs: marshal LearnAll's native bool parameters as UnmanagedType.I1. The default 4-byte bool marshalling corrupts later stack arguments and segfaults on arm64 (works on x64 by luck).

Testing

Built native (Release + Debug) and ran the SymSGD trainer tests on Apple Silicon (arm64):

  • TestEstimatorSymSgdClassificationTrainer
  • TestEstimatorSymSgdInitPredictor
  • SimpleTrainAndPredictSymSGD

3 passed, 0 failed. Without the bool marshalling fix, these crash the test host with a SIGSEGV inside LearnAll.

Notes

  • The initial arm enablement scaffolding (MklImportsArm skeleton, CMake gating, SparseBLAS.h calling-convention guard) is based on prior work by @anicka-net (credited as co-author).
  • Broader MKL consumers in Microsoft.ML.Mkl.Components (OLS, VectorWhitening) and Microsoft.ML.TimeSeries still require a real BLAS/LAPACK and are out of scope here.

@vladimir-aubrecht

Copy link
Copy Markdown
Contributor Author

@dotnet-policy-service agree company="Microsoft"

@vladimir-aubrecht
vladimir-aubrecht marked this pull request as ready for review August 11, 2026 12:28
Copilot AI lite review requested due to automatic review settings August 11, 2026 12:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables SymbolicSgdLogisticRegression / SymSgdNative on arm/arm64 by adding an ARM-specific MklImports shim (implementing the small subset of CBLAS APIs SymSGD needs), wiring it into the native build, and fixing managed P/Invoke marshalling that can crash on arm64.

Changes:

  • Add src/Native/MklImportsArm/ to build a self-contained MklImports shim on arm/arm64 and link SymSgdNative against it.
  • Update native build gating so SymSgdNative is built on arm/arm64 and shipped next to managed assemblies.
  • Fix LearnAll P/Invoke bool marshalling to avoid stack corruption / SIGSEGV on arm64.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Native/SymSgdNative/SparseBLAS.h Makes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txt Adjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.c Implements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txt Adds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txt Enables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.cs Fixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targets Ensures MklImports and SymSgdNative are copied for arm/arm64 outputs (no longer removed).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Native/SymSgdNative/CMakeLists.txt Outdated
Comment thread src/Native/SymSgdNative/SparseBLAS.h
Comment thread src/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.88%. Comparing base (240a849) to head (bde8e6c).

Files with missing lines Patch % Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs 33.33% 1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs 85.71% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7671   +/-   ##
=======================================
  Coverage   69.88%   69.88%           
=======================================
  Files        1487     1487           
  Lines      276214   276223    +9     
  Branches    28287    28289    +2     
=======================================
+ Hits       193019   193045   +26     
+ Misses      75708    75692   -16     
+ Partials     7487     7486    -1     
Flag Coverage Δ
Debug 69.88% <70.00%> (+<0.01%) ⬆️
production 64.07% <85.71%> (+<0.01%) ⬆️
test 89.82% <33.33%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs 94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs 100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs 77.23% <85.71%> (+0.08%) ⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs 69.51% <33.33%> (-0.11%) ⬇️

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Vladimir Aubrecht and others added 4 commits August 26, 2026 14:33
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.

- MklImportsArm: implement the four CBLAS routines SymSGD needs
  (sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
  dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
  in the CI cross-compilation sysroots (which ship no BLAS). Export the
  symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
  against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
  to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
  LearnAll as I1. The default 4-byte bool marshalling corrupts later
  stack arguments and segfaults on arm64.

Fixes dotnet#5798

Co-authored-by: Anna Maresova <anicka@anicka.net>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Descriptor, fix misleading comment

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rts off arm

Two CI failures on this PR:

1. macOS arm64 build: SymSgdNative linked OpenMP via the hardcoded Intel Homebrew
   path /usr/local/opt/libomp, which holds an x86_64 libomp on Apple Silicon, so
   linking failed with undefined __kmpc_*/omp_* symbols. Use `brew --prefix libomp`
   like MatrixFactorizationNative already does, so it resolves on Intel and arm Macs.

2. Windows/macOS arm64 tests: shipping the arm MklImports shim as libMklImports made
   NativeDependencyFact("MklImports") stop skipping every MKL-gated test. The shim only
   implements the 4 CBLAS routines SymSGD needs, so OLS/PCA-whitening/TimeSeries tests
   ran and failed with EntryPointNotFound (LAPACKE_dsytrd) / DllNotFound (MklProxyNative).

Fix by making SymSgd self-contained on arm and not shipping a separate libMklImports:
- SymSgdNative compiles the MklImportsArm CBLAS shim directly (no separate library),
  and the arm MklImportsArm target / its CMakeLists are removed.
- Directory.Build.targets keeps MklImports removed on arm (only SymSgdNative is copied).
- SymSgdClassificationTrainer skips the ErrorMessage(0) MKL-preload on arm (there is no
  MklImports to preload there).
- SymSgd tests are gated on NativeDependencyFact("SymSgdNative") instead of "MklImports"
  so they still run on arm; the other MKL tests skip as they did before this PR.

Verified on arm64 macOS: SymSgdNative links and is self-contained (cblas_* internal,
no MklImports dependency), SymSgd tests run and pass, and OLS/whitening tests skip.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follow-up to the arm64 SymSgd enablement:

- macOS arm64: the cross-compilation runner only has an x86_64 libomp, and SymSGD needs
  OpenMP, so SymSgdNative cannot link there. Build it on Windows/Linux arm only and don't
  copy it on macOS arm, so its dependent tests skip there (they already skip the full-MKL
  tests). SymSgd remains enabled on Windows and Linux arm64.

- BinaryClassifierSymSgdTest is a strict baseline comparison against the win-x64 baseline;
  SymSGD produces slightly different numbers on arm, so skip it on arm (it already skips on
  Linux). The trainer itself stays covered on arm by the SymSgdClassificationTests estimators.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@matouskozak

Copy link
Copy Markdown
Member

@vladimir-aubrecht

vladimir-aubrecht commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — right now the PR builds and tests SymSgdNative on Windows/Linux arm64 but this packaging exclusion means it wouldn't ship in the arm64 NuGet, so consumers wouldn't actually get it. I think we should remove the exclusion here so the feature is delivered, but scoped to the platforms where we actually build it: include SymSgdNative for win-arm64 and linux-arm64, and keep it excluded for osx-arm64 (where it isn't built, since the macOS cross-compilation runner has no arm64 libomp). Done in bde8e6c — the packaging condition now includes SymSgdNative for win-arm64 and linux-arm64 and excludes only osx-arm64.

The packaging exclusion kept SymSgdNative out of all arm NuGet packages, so even
though this PR builds and tests it on Windows/Linux arm64, consumers wouldn't get it.
Include it for arm64/arm except on macOS, where SymSgdNative isn't built (the macOS
cross-compilation runner has no arm64 libomp). Replaces the stale TODO.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add substitutes for 4 IntelMKL methods so SymSgd can be added to non x86/x64 builds

3 participants