Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64 - #7671

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

Enable SymbolicSgdLogisticRegression (SymSgdNative) on arm64#7671
vladimir-aubrecht wants to merge 7 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-containedlibMklImports 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
ContributorAuthor

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

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

CopilotAI 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
FileDescription
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable across Windows vs non-Windows builds.
src/Native/SymSgdNative/CMakeLists.txtAdjusts how MklImports is resolved/linked on arm platforms.
src/Native/MklImportsArm/MklImportsArm.cImplements the minimal CBLAS subset + DFTI stubs for arm/arm64 as a self-contained shim.
src/Native/MklImportsArm/CMakeLists.txtAdds CMake target to build/install the ARM MklImports shim.
src/Native/CMakeLists.txtEnables building SymSgdNative on arm/arm64 and adds MklImportsArm to the build graph.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csFixes P/Invoke bool marshalling for LearnAll to prevent arm64 crashes.
Directory.Build.targetsEnsures 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 threadsrc/Native/SymSgdNative/CMakeLists.txt Outdated
Comment threadsrc/Native/SymSgdNative/SparseBLAS.h
Comment threadsrc/Native/MklImportsArm/MklImportsArm.c Outdated
@codecov

codecovBot 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 (7a7d8dd).
⚠️ Report is 2 commits behind head on main.

Files with missing linesPatch %Lines
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs33.33%1 Missing and 1 partial ⚠️
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs85.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 193040 +21 + Misses 75708 75691 -17 - Partials 7487 7492 +5 
FlagCoverage Δ
Debug69.88% <70.00%> (+<0.01%)⬆️
production64.07% <85.71%> (+<0.01%)⬆️
test89.82% <33.33%> (-0.01%)⬇️

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

Files with missing linesCoverage Δ
.../Scenarios/Api/Estimators/SimpleTrainAndPredict.cs94.73% <ø> (ø)
...sts/TrainerEstimators/SymSgdClassificationTests.cs100.00% <ø> (ø)
...t.ML.Mkl.Components/SymSgdClassificationTrainer.cs77.23% <85.71%> (+0.08%)⬆️
...est/Microsoft.ML.Predictor.Tests/TestPredictors.cs69.51% <33.33%> (-0.11%)⬇️

... and 7 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 Aubrechtand 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.
Fixesdotnet#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
ContributorAuthor

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>
Run macOS arm64 CI and native asset builds on an Apple Silicon image so Homebrew provides a matching OpenMP runtime. Build and package SymSgdNative for osx-arm64, prepare libomp dynamically for Helix, and document the dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@matouskozakmatouskozak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looking good, I left a couple of comments to clarify my understanding of the PR.

Comment threadsrc/Native/SymSgdNative/CMakeLists.txt
Comment threadtest/Microsoft.ML.Predictor.Tests/TestPredictors.cs Outdated
Comment thread.vsts-dotnet-ci.yml Outdated
Comment threadDirectory.Build.targets Outdated
Apply MSVC mitigations to the ARM C shim, add macOS ARM64 SymSGD baselines with an appropriate numeric tolerance, rename the native macOS ARM64 CI job, and clarify the native assembly removal comment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@vladimir-aubrecht@matouskozak