Skip to content

Repository files navigation

Metal GPU Computing for Scientific C++ on Apple Silicon

GPU-accelerated scientific computing on Apple Silicon using Metal Shading Language (MSL) and C++ (metal-cpp), with Python bindings via pybind11.

This repository accompanies "Seamless GPU acceleration for C++ based physics using the M1's unified processing units" (arXiv:2206.01791).

Blog posts:

Examples

DirectoryDescriptionMetal Kernels
01-MetalAdderBasic GPU array additionadd_arrays
02-GeneralArrayOperations1D ops: add, multiply, SAXPY, central differenceadd_arrays, multiply_arrays, saxpy, central_diff
03-2DKernels2D spatial kernels: quadratic, Laplacian (5pt & 9pt)quadratic2d, laplacian2d, laplacian2d9p
04-ComputeCompute-heavy: Mandelbrot fractal, N-body gravitymandelbrot, nbody_forces, nbody_integrate
05-WavePropagation2D elastic wave propagation (Virieux staggered grid)stress_update, velocity_update, apply_damping

Prerequisites

  • macOS on Apple Silicon (M1/M2/M3/M4)
  • Xcode and Command Line Tools (xcode-select --install)
  • CMake 3.21+ (brew install cmake)
  • For CPU baselines: brew install llvm libomp
  • For Python bindings: python3, numpy, pybind11

Building

git clone --recurse-submodules https://github.com/larsgeb/m1-gpu-cpp.git
cd m1-gpu-cpp
cmake -B build
cmake --build build

Run an example:

cd build/02-GeneralArrayOperations && ./example_02

Tests

cd build && ctest --output-on-failure

Tests verify GPU results against CPU reference implementations.

Python bindings

python3 -m venv .venv &&source .venv/bin/activate
pip install numpy pybind11 matplotlib jupytext
cmake -B build -Dpybind11_DIR=$(python3 -c "import pybind11; print(pybind11.get_cmake_dir())")
cmake --build build

Quick test:

importsys; sys.path.insert(0, "build")
importnumpyasnpimportm1_gpu_opsasmetalctx=metal.MetalContext()
ctx.load_library("build/02-GeneralArrayOperations/ops.metallib")
x=np.random.rand(100_000).astype(np.float32)
y=np.random.rand(100_000).astype(np.float32)
result=metal.add_arrays(ctx, x, y)

Available functions

FunctionLibraryDescription
add_arrays(ctx, x, y)02-…/ops.metallibElement-wise addition
multiply_arrays(ctx, x, y)02-…/ops.metallibElement-wise multiplication
saxpy(ctx, a, x, y)02-…/ops.metallibScalar a*x + y
laplacian2d(ctx, u)03-…/ops.metallib5-point Laplacian stencil
laplacian2d9p(ctx, u)03-…/ops.metallib9-point Laplacian stencil
mandelbrot(ctx, …)04-…/ops.metallibMandelbrot set rendering
nbody_step(ctx, …)04-…/ops.metallibSingle N-body gravity step
nbody_simulate(ctx, …)04-…/ops.metallibMulti-step N-body (data on GPU)
diffuse_steps(ctx, …)03-…/ops.metallibMulti-step heat diffusion (data on GPU)
elastic_wave_propagate(ctx, …)05-…/ops.metallib2D elastic wave propagation

Notebooks

The demo notebooks are stored as jupytext light-format .py files for clean version control. To open them:

# Convert to .ipynb and open in Jupyter
jupytext --to notebook demo.py
jupyter notebook demo.ipynb
NotebookDescription
demo.py1D/2D operations, Mandelbrot, N-body, diffusion — with GPU vs NumPy benchmarks
wave_demo.py2D elastic wave propagation: homogeneous/layered media, seismograms, GPU benchmarks

Project structure

01-MetalAdder/ # Example 1: Basic GPU array addition
02-GeneralArrayOperations/ # Example 2: 1D array operations
03-2DKernels/ # Example 3: 2D spatial kernels
04-Compute/ # Example 4: Mandelbrot & N-body
05-WavePropagation/ # Example 5: 2D elastic wave propagation
metal-cpp/ # metal-cpp headers (git submodule)
python/ # pybind11 bindings & Python package
tests/ # CTest correctness tests
paper/ # Benchmark scripts & figures for arXiv paper

License

BSD 3-Clause — see LICENSE.

About

Metal Shading Language on Apple M1's GPU for scientific C++.

Topics

Resources

Stars

121 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages