Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 AI & Machine LearningGraphics & Games

WWDC21 · 29 min · AI & Machine Learning / Graphics & Games

Accelerate machine learning with Metal Performance Shaders Graph

Metal Performance Shaders Graph is a compute engine that helps you build, compile, and execute customized multidimensional graphs for linear algebra, machine learning, computer vision, and image processing. Discover how MPSGraph can accelerate the popular TensorFlow platform through a Metal backend for Apple products. Learn how to add control flow to your graphs, manage the graph compilation for optimal performance, and use the MPSGraph operations to accelerate the hardest compute applications with only a few lines of code.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 15 snippets

Control dependencies 1 swift · at 8:35 ↗
// Execute the graph
let results = graph.run(feeds: [inputTensor: inputs],
                        targetTensors: [exp],
                        targetOperations: [assign])
Control dependencies 2 swift · at 9:01 ↗
// Create control dependency

let exp = graph.controlDependency(with: [assign],
                                  dependentBlock: { 
                                      return [graph.exponent(with: input, 
                                                             name: nil)]
                                  },
                                  name: nil)

// Execute the graph

let results = graph.run(feeds: [inputTensor: inputs],
                        targetTensors: [exp],
                        targetOperations: nil)
Evaluation method swift · at 14:42 ↗
// Create the graph

let placeholder0 = graph.placeholder(shape: [1, 3], 
                                     dataType: .float32, 
                                     name: nil)

let placeholder1 = graph.placeholder(shape: [2, 1], 
                                     dataType: .float32, 
                                     name: nil)

let addTensor = graph.addition(placeholder0, 
                               placeholder1, 
                               name: nil)

// Compile the graph into an executable

let executable = graph.compile(with: nil,
                               feeds: [placeholder0: MPSGraphShapedType(shape: [1, 3], 
                                                                        dataType: .float32),
                                       placeholder1: MPSGraphShapedType(shape: [2, 1], 
                                                                        dataType: .float32)],
                               targetTensors: [addTensor],
                               targetOperations: nil,
                               compilationDescriptor: nil)

// Execute the graph into an executable

let fetch = executable.run(with: commandQueue,
                           inputs: [MPSGraphTensorData(input0),        
                                    MPSGraphTensorData(input1)],
                           results: nil,
                           executionDescriptor: nil)
Disabling the type inference pass swift · at 16:38 ↗
// Create the graph compilation descriptor

let descriptor = MPSGraphCompilationDescriptor()

// Disable type inference

descriptor.disableTypeInference()

// Compile the graph into an executable

let executable = graph.compile(with: nil,
                               feeds: /* feeds */,
                               targetTensors: /* target tensors */,
                               targetOperations: nil,
                               compilationDescriptor: descriptor)

// execute the graph
If/else in batch normalization swift · at 19:22 ↗
// Different behavior during inference and training

let results = graph.if(isTraining,
                       then: { ... },    // compute mean and variance
                       else: { ... },    // use running_mean and running_variance
                       name: nil)
If/else swift · at 19:46 ↗
let predicate = graph.lessThan(a, 
                               b, 
                               name: nil)

let results = graph.if(predicate,
    then: {[
        graph.addition(a, 
                       b, 
                       name: nil)
    ]},
    else: {[
        graph.subtraction(a, 
                          b, 
                          name: nil)
    ]},
    name: nil)
For loop 1 swift · at 20:58 ↗
var result = input0

for i in 0..<4 {
    result *= input1
}
For Loop 2 swift · at 21:12 ↗
// Initialize inputs

let input0 = graph.placeholder(shape: [], 
                               dataType: .int32, 
                               name: nil)

let input1 = graph.placeholder(shape: [], 
                               dataType: .int32, 
                               name: nil)
        
let numberOfIterations = graph.constant(4, 
                                        shape: [], 
                                        dataType: .int32)
For Loop 3 swift · at 21:33 ↗
// Define Body

let body = {
    (index: MPSGraphTensor, iterationArguments: [MPSGraphTensor]) -> [MPSGraphTensor] in
        let iterationResult = graph.multiplication(iterationArguments[0], input1, name: nil)
        return [iterationResult]
}
For Loop 4 swift · at 21:52 ↗
// Create for loop operation

let result = graph.for(numberOfIterations: numberOfIterations,
                       initialIterationArguments: [input0],
                       body: body)
While loop 1 swift · at 22:51 ↗
var result = initialValue

while result < threshold {
    result *= multiplier
}
While loop 2 swift · at 23:01 ↗
// Evaluate condition

let condition = {
    (inputs: [MPSGraphTensor], returnTensors: NSMutableArray) -> MPSGraphTensor in
        let predicate = graph.lessThan(inputs[0], threshold, name: nil)
        returnTensors.add(inputs[0])
        return predicate
}
While loop 3 swift · at 23:22 ↗
// Define body

let body = {
    (inputs: [MPSGraphTensor]) -> [MPSGraphTensor] in
        let iterationResult = graph.multiplication(inputs[0], multiplier, name: nil)
        return [iterationResult]
}
While loop 4 swift · at 23:33 ↗
// Create while loop operation

let results = graph.while(initialInputs: [initialValue],
                          before: condition,
                          after: body,
                          name: nil)
Edge filter swift · at 25:00 ↗
// Apply the laplacian edge filter on the source image

let edges = graph.stencil(with: source, 
                          weights: laplacianWeights, 
                          descriptor: desc, 
                          name: nil)

Resources