Enable SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@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 SymSgdNative on ARM64 including macOS - #7678

Closed
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd
Closed

Enable SymSgdNative on ARM64 including macOS#7678
matouskozak wants to merge 6 commits into
mainfrom
matouskozak-macos-arm64-symsgd

Conversation

@matouskozak

Copy link
Copy Markdown
Member

Summary

Extends the ARM64 SymSgd work from #7671 to macOS by building native assets on Apple Silicon agents.

  • builds SymSgdNative for ARM/ARM64 with the self-contained CBLAS shim
  • uses macOS-15-arm64 Azure Pipelines agents for native macOS ARM64 builds
  • packages ARM64 libomp.dylib beside libSymSgdNative.dylib
  • links OpenMP through @loader_path/libomp.dylib
  • removes the macOS ARM64 exclusions so existing SymSgd tests run on ARM64 Helix
  • includes the LLVM OpenMP redistribution notice

Validation

  • clean and incremental macOS ARM64 native builds
  • Debug and Release native package asset generation
  • NuGet package contains runtimes/osx-arm64/native/libSymSgdNative.dylib and libomp.dylib
  • otool confirms @loader_path/libomp.dylib
  • existing targeted SymSgd tests: 3 passed
  • reviewed independently with Claude Opus 5, Claude Sonnet 5, and Gemini 3.7 Flash

Related to #5798 and #7671.

Vladimir Aubrechtand others added 6 commits August 27, 2026 19:24
Build SymSgdNative and a small self-contained libMklImports shim on
arm/arm64 so the SymbolicSgdLogisticRegression trainer works there
without Intel MKL.
- MklImportsArm: implement the four CBLAS routines SymSGD needs
(sdot, saxpy, sdoti, saxpyi) as portable C with no external BLAS
dependency, plus DFTI stubs. Drop find_package(BLAS) so it configures
in the CI cross-compilation sysroots (which ship no BLAS). Export the
symbols explicitly since the native build uses -fvisibility=hidden.
- CMake: build MklImportsArm + SymSgdNative on arm, link SymSgdNative
against the shim, and make the CBLAS calling convention portable.
- Directory.Build.targets: ship libMklImports and libSymSgdNative next
to the managed assemblies on arm.
- SymSgdClassificationTrainer: marshal the native bool parameters of
LearnAll as I1. The default 4-byte bool marshalling corrupts later
stack arguments and segfaults on arm64.
Fixes#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>
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>
Build macOS ARM64 assets on Apple Silicon agents and package the native OpenMP runtime beside SymSgdNative using loader-relative linkage.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6486565-2c30-46ac-b951-6e6468408258
CopilotAI lite review requested due to automatic review settings August 27, 2026 18:01

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

Extends ML.NET’s SymSGD native enablement to macOS ARM64 by building SymSgdNative on Apple Silicon agents, packaging required native dependencies (notably libomp.dylib), and updating tests/packaging to run SymSGD scenarios on ARM64.

Changes:

  • Build SymSgdNative on ARM/ARM64 by compiling the ARM CBLAS shim into the library and updating CMake gating accordingly.
  • Enable macOS ARM64 native builds/packaging by using Apple Silicon agents and shipping libomp.dylib beside libSymSgdNative.dylib with @loader_path linkage.
  • Update test gating to depend on SymSgdNative and remove macOS ARM64 exclusions so SymSGD tests run on ARM64 Helix.

Reviewed changes

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

Show a summary per file
FileDescription
THIRD-PARTY-NOTICES.TXTAdds LLVM OpenMP runtime redistribution notice.
test/Microsoft.ML.Tests/TrainerEstimators/SymSgdClassificationTests.csSwitches native dependency gating from MklImports to SymSgdNative.
test/Microsoft.ML.Tests/Scenarios/Api/Estimators/SimpleTrainAndPredict.csSwitches SymSGD scenario test gating to SymSgdNative.
test/Microsoft.ML.Predictor.Tests/TestPredictors.csGates SymSGD baseline test on SymSgdNative and skips strict baseline compare on ARM/ARM64.
src/Native/SymSgdNative/SparseBLAS.hMakes CBLAS calling convention portable and fixes const-correctness for dense vector usage.
src/Native/SymSgdNative/CMakeLists.txtAdds ARM shim compilation path and macOS ARM64 libomp packaging / @loader_path install-name handling.
src/Native/Native.projPackages SymSgdNative broadly and adds macOS ARM64 libomp.dylib asset; refines symbols packaging conditions.
src/Native/MklImportsArm/MklImportsArm.cIntroduces ARM CBLAS shim implementation (and DFTI stubs) used to enable SymSGD without MKL on ARM.
src/Native/CMakeLists.txtBuilds SymSgdNative on ARM and documents why a separate MklImports isn’t built there.
src/Microsoft.ML.Mkl.Components/SymSgdClassificationTrainer.csSkips MKL load trigger on ARM and fixes P/Invoke bool marshalling for LearnAll.
eng/helix.projCopies the correct libomp.dylib for macOS ARM64 Helix runs and removes SymSgd install-name patching from Helix step.
Directory.Build.targetsEnsures libomp.dylib is copied next to managed assemblies on macOS ARM64 when SymSgdNative is referenced.
build/vsts-ci.ymlUses macOS ARM64 agents for Apple Silicon native asset generation.
.vsts-dotnet-ci.ymlRenames/retargets macOS ARM64 job to macOS-15-arm64 pool image.

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

Comment on lines +17 to +24
execute_process(
COMMAND brew --prefix libomp
RESULT_VARIABLE BREW_LIBOMP
OUTPUT_VARIABLE BREW_LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
SET(OPENMP_LIBRARY "${BREW_LIBOMP_PREFIX}/lib/libomp.dylib")
include_directories("${BREW_LIBOMP_PREFIX}/include")
Comment on lines +5 to +10
// ARM replacement for Intel MKL (libMklImports.so).
//
// This provides a small, self-contained libMklImports for arm/arm64 that
// covers exactly the symbols SymSGD needs, with no external BLAS dependency.
// That is important because the cross-compilation sysroots used in CI do not
// ship OpenBLAS (or any system BLAS), so linking against one is not an option.
Comment on lines +18 to +24
// MKL DFTI (FFT) functions are stubbed — they are referenced by the managed
// MKL Components initializer but not used by SymSGD. The stubs return error
// codes so any actual FFT call fails cleanly rather than crashing.

// The native build is compiled with -fvisibility=hidden, so every symbol that
// must be visible to SymSgdNative (the CBLAS routines) or to the managed
// P/Invoke layer (DftiErrorMessage) has to be exported explicitly.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@matouskozak