In this episode, we’ll explore Metal’s library for image processing, matrix and vector operations, and neural network layers: Metal Performance Shaders (MPS). MPS integrates seamlessly into the Metal pipeline and is highly optimized for performance. However, its documentation often lacks the depth needed to cover all the nuances of using the library effectively.
First of all, the official documentation is an invaluable resource. The library includes a vast collection of ready-to-use algorithms, making it impossible to cover everything here. Instead, this episode will give you a sense of what’s available and what to expect.
There are three main sections in Metal Performance Shaders: image filters, neural networks, and matrices and vectors. Personally, I’ve mostly worked with image filters and matrices, as neural networks are more straightforward to implement using MPSGraph (which we’ll cover in the next episode).
MPS introduces its own set of types, which are essentially wrappers around native Metal objects. However, certain MPS operations require these specific types instead of Metal’s standard ones:
MPSImage: Represents a collection of one or more MTLTexture objects with identical dimensions, allowing you to simulate an image with more than four channels.MPSMatrix: Combines a MTLBuffer with metadata, including data alignment, the type of elements, and the number of rows and columns, to represent a matrix efficiently.MPSVector: A one-dimensional equivalent of MPSMatrix, designed for vector operations while retaining similar metadata features.If some of these terms are unfamiliar, don’t hesitate to look them up or explore basic image processing techniques. It’s a fascinating and rewarding area to learn about!
MPS provides support for fully connected, convolutional, and recurrent neural networks. Each section includes layers for arithmetic, pooling, convolution, fully connected operations, neuron activation, softmax, normalization, upsampling, resampling, dropout, loss computation, filtering, and layer concatenation. While this functionality is robust and sufficient for most machine learning tasks, using MPSGraph is often simpler and more intuitive when applying Metal to machine learning workflows.
Here, we have tools for fundamental operations like addition and multiplication, as well as advanced mathematical capabilities, including LU decomposition, triangular matrix solvers, and Cholesky decomposition.
Why choose the Euclidean Distance Transform as an example? It’s simple and perhaps a bit unexciting, but it’s perfect for illustrating what’s happening under the hood and showcasing a typical use case of MPS. Its straightforward nature allows us to focus on understanding the mechanics and benefits of using Metal Performance Shaders without getting lost in complex computations.
Let’s create a straightforward method to compute a Euclidean distance field for a texture:
func computeDistanceField(for source: MTLTexture, in commandBuffer: MTLCommandBuffer) -> MTLTexture {
let device = source.device
let result = createTexture(device: device, // (1)
width: source.width,
height: source.height,
format: source.pixelFormat)
let mpsDistanceTransform = MPSImageEuclideanDistanceTransform(device: device) // (2)
mpsDistanceTransform.encode( // (3)
commandBuffer: commandBuffer,
sourceTexture: source,
destinationTexture: result)
return result
}
Now, let’s examine what happens on the GPU side and is hidden by Metal. To do this, we can capture our command buffer in Xcode:

Though we don’t have access to the kernel source code, we can still understand the principles behind its implementation and reproduce it on our side. Let me break this down at a very high level.
The process consists of three passes, what we can deduce not only from the kernel names but also by observing the intermediate textures and buffers.
During the vertical passes, MPS creates two additional textures (as indicated by texture names) and two intermediate buffers. These allocations can lead to temporary peaks in memory usage, so don’t be alarmed if you observe increased consumption during this stage.