Skip to main content

GPU-accelerated scikit-learn via Apple Metal

Project description

skmetal

Apple Silicon GPU acceleration for scikit-learn

Platform Python License CI

import skmetal
from sklearn.linear_model import LinearRegression

@skmetal.accelerate
def model():
    return LinearRegression()

m = model()
m.fit(X_train, y_train)
m.predict(X_test)

Overview

skmetal executes scikit-learn estimators on Apple Silicon GPUs via Metal Performance Shaders and custom Metal compute kernels. Decorate any function that returns an estimator with @skmetal.accelerate and fit()/predict() run on the GPU — no code changes required.

Apple Silicon's unified memory architecture enables zero-copy data sharing: numpy arrays are passed directly to Metal via bytesNoCopy, eliminating data transfer overhead.


Requirements

  • macOS 14+
  • Apple Silicon (M1-M5)
  • Python 3.10-3.12
  • Swift 6.1 (xcode-select --install)
  • scikit-learn >= 1.5

Installation

pip install skmetal

Note: macOS 14+ and Apple Silicon required. Xcode not needed for the pip package.

From source

git clone https://github.com/abderahmane-ai/skmetal.git
cd skmetal
bash build.sh
pip install -e .

Usage

Decorator (recommended)

import skmetal
from sklearn.linear_model import LinearRegression

@skmetal.accelerate
def model():
    return LinearRegression()

m = model()
m.fit(X, y)
m.predict(X_test)

The decorator also works with pipelines:

@skmetal.accelerate
def pipeline():
    return Pipeline([
        ("scaler", StandardScaler()),
        ("clf", LogisticRegression()),
    ])

pipe = pipeline()
pipe.fit(X, y)
pipe.predict(X_test)

Function call

model = skmetal.accelerate(LinearRegression())
model.fit(X, y)

Context manager

with skmetal.accelerate_context():
    model = LinearRegression()
    model.fit(X, y)

Supported Estimators

Estimator GPU Strategy Speedup
LinearRegression Normal equations via MPS GEMM 5.93x
Ridge Fused centering + XTX + XTy (1 dispatch) 1.16x
LogisticRegression IRLS (3-5 Newton iterations, fused) 0.91x
Lasso Coordinate descent + GPU residual updates --
ElasticNet Coordinate descent + GPU residual updates --
TruncatedSVD Randomized SVD, no centering (all BLAS-3) 2.53x
KMeans Single fused command buffer (all iterations on GPU) 0.69x
DBSCAN GPU pairwise distance + per-point neighbor counting --
GaussianNB GPU mean/var per class --
StandardScaler Fused Welford (1 dispatch) 8.27x
MinMaxScaler Column min/max with threadgroup tree reduction --
RobustScaler GPU quantile approximation --
KNeighborsClassifier GPU pairwise distance + fused voting --
KNeighborsRegressor GPU pairwise distance + fused averaging --
NearestNeighbors GPU pairwise distance + index --
HistGradientBoostingRegressor C++ HGBT from sklearn (no custom GPU) --
HistGradientBoostingClassifier C++ HGBT from sklearn (no custom GPU) --

Estimators below 1.0x speedup are dispatch-limited at n <= 50K. Speedup improves to 2-5x at n >= 500K where compute dominates overhead.


Architecture

Zero-copy pipeline

numpy array -> np.ctypes.data -> UnsafeMutableRawPointer -> MTLBuffer(bytesNoCopy:) -> GPU
                   |                                                    |
                   +--------- same physical memory ---------------------+

Metal kernels (14 files)

Kernel file Operations
ReductionKernels.metal reduce_sum, reduce_mean_var (Welford)
ArgminKernels.metal argmin_rows
KMeansKernels.metal assign, partial_sum, combine, normalize, batch fused
KNNKernels.metal tile top-k, merge, fused vote classify/regress
PairwiseDistKernels.metal pairwise_distance_squared, pairwise_distance_direct
DistanceKernels.metal row_norm_sq, compute_mindists, distance_correct
IrlsKernels.metal irls_weight, scale_rows, compute_linear_irls, compute_error_scale, l2_reg_irls, multinomial_hessians
CenterColumns.metal column_means, center_columns
ElementWiseKernels.metal sigmoid, subtract, add_scalar, axpy, norm_sq, transpose_f32, row_max, row_sum, softmax, negate
ExtraKernels.metal soft_threshold, column_transform, scale_f32, sv_init, sv_hook, sv_shortcut
StandardScalerKernels.metal scaler_fit (fused Welford)
GemmKernels.metal gemm_simple (fallback)
MinMaxKernels.metal column_minmax (threadgroup tree reduction)
TreeKernels.metal tree_predict, tree_predict_all

Swift bridge (47 C-callable functions)

All skmetal_* functions use @_cdecl for direct ctypes export. Every function accepts raw pointers.

Project structure

skmetal/
  skmetal/
    __init__.py
    _bridge.py           ctypes -> Swift (47 functions)
    _config.py           Config dataclass
    _dispatch.py         estimator registry + wrapping
    accelerate.py        @accelerate decorator + accelerate_context
    estimators/
      _base.py           BaseGPUEstimator abstract class
      _registry.py       Estimator registry (17 estimators)
      linear_model.py    LinearRegression, Ridge, LogisticRegression, Lasso, ElasticNet
      cluster.py         KMeans, DBSCAN
      decomposition.py   TruncatedSVD
      ensemble.py        HistGradientBoostingRegressor, HistGradientBoostingClassifier
      naive_bayes.py     GaussianNB
      neighbors.py       KNeighborsClassifier, KNeighborsRegressor, NearestNeighbors
      preprocessing.py   StandardScaler, MinMaxScaler, RobustScaler
    utils.py
  skmetal_bridge/        Swift + Metal
    Sources/SkMetalBridge/
      Bridge.swift       47 @_cdecl exports
      MetalContext.swift
      Kernels/*.metal    14 Metal kernel files
  benchmarks/
    run_compare.py       benchmark runner
    benchmark_suite.py   full suite
    baseline.json
  tests/
    test_correctness.py  18 estimator correctness tests
    test_dispatch.py     7 dispatch logic tests
    test_kernels.py      55 kernel unit tests
    test_config.py       13 config API tests
    test_accelerate.py   20 accelerate edge-case tests
    test_stress.py       27 edge-case/stress tests
    conftest.py          shared fixtures
  build.sh
  pyproject.toml
  .github/workflows/
    ci.yml               build + test + benchmark regression
    release.yml          PyPI publish on tag
  LICENSE                MIT

Tests

test_correctness   18/18 pass — estimator parametrizations + pipeline + device info
test_dispatch       7/7  pass — registry, wrapping, pipeline, decorator
test_kernels       55/55 pass — all 14 kernel files covered
test_config        13/13 pass — config API, dtype rejection, threshold, reset
test_accelerate    20/20 pass — decorator, context manager, edge cases
test_stress        27/27 pass — contiguity, shape mismatch, extremes, CPU fallback

Benchmarks

python benchmarks/run_compare.py

Development

git clone https://github.com/abderahmane-ai/skmetal.git
cd skmetal
bash build.sh
pip install -e ".[dev]"
pytest tests/
python benchmarks/run_compare.py

Adding a new estimator

  1. Create skmetal/estimators/my_model.py with MetalMyModel(BaseGPUEstimator)
  2. Register in _registry.py (GPU_ESTIMATORS + PIPELINE_PATTERNS)
  3. Add module path in _dispatch.py (module_map)
  4. Write a Metal kernel if needed
  5. Add a parametrized test case in test_correctness.py

License

MIT License. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skmetal-0.3.3.tar.gz (27.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skmetal-0.3.3-py3-none-any.whl (174.1 kB view details)

Uploaded Python 3

File details

Details for the file skmetal-0.3.3.tar.gz.

File metadata

  • Download URL: skmetal-0.3.3.tar.gz
  • Upload date:
  • Size: 27.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skmetal-0.3.3.tar.gz
Algorithm Hash digest
SHA256 2be86c4b32d1079404cd7ac33c99c8cfc94fd6729ceee9bbe0efc4d6d9ef59a4
MD5 5d85d6bbbe9e26dd07d2aef2e91e4b7c
BLAKE2b-256 e42d13df30f14b31d59150db025f476c881399c5dd3f1ff3ea84ec1883dfa43e

See more details on using hashes here.

Provenance

The following attestation bundles were made for skmetal-0.3.3.tar.gz:

Publisher: release.yml on abderahmane-ai/skmetal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file skmetal-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: skmetal-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 174.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skmetal-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 8e0dcee6853e7a4df4eda9008eaf2d74ba8bb103dd1e0f256b70a2d1ea32e8c5
MD5 6a6fe0700a5ceb61245447a08d86a539
BLAKE2b-256 2e2bf8994f53893da5d72a859d2ca2f60b0569e582cafb6266059580ce59a6ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for skmetal-0.3.3-py3-none-any.whl:

Publisher: release.yml on abderahmane-ai/skmetal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page