Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

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

Conversation

@vladimir-aubrecht

Copy link
Copy Markdown

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.

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>
@vladimir-aubrecht

Copy link
Copy Markdown
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
Vladimir Aubrecht and others added 2 commits August 11, 2026 14:50
…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>
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 69.76%. Comparing base (548d4d0) to head (d87714c).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs 85.71% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7671      +/-   ##
==========================================
+ Coverage   69.59%   69.76%   +0.16%     
==========================================
  Files        1484     1486       +2     
  Lines      273606   275796    +2190     
  Branches    27949    28200     +251     
==========================================
+ Hits       190410   192401    +1991     
- Misses      75832    75936     +104     
- Partials     7364     7459      +95     
Flag Coverage Δ
Debug 69.76% <85.71%> (+0.16%) ⬆️
production 63.93% <85.71%> (+0.09%) ⬆️
test 89.80% <ø> (+0.16%) ⬆️

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

Files with missing lines Coverage Δ
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs 69.62% <ø> (ø)
.../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%) ⬆️

... and 20 files with indirect coverage changes

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

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>
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

2 participants