Sample CodemacOSReviewed 2026-07-21View on Apple Developer

Training a Neural Network with Metal Performance Shaders

At a glance

Item Summary
Purpose Use an MPS neural network graph to train a simple neural network digit classifier.
App architecture A C/Objective-C header, Objective-C++ sample centered on main, with direct use of Metal, MetalPerformanceShaders, random.
Main patterns Delegate or data-source callbacks
Project style 10 scanned source file(s) across C/Objective-C header, Objective-C++, organized around ranked entry, type, and file boundaries.
Execution model No structured execution marker indexed; callback threading requires source review.
State/event model No structured observation or publisher-scheduling marker indexed.
Key frameworks/packages Foundation, Metal, MetalPerformanceShaders, random, zlib.h; these are source dependencies, not architecture labels.

Project structure

Source bundle/
├── MPSTrainingClassifier/
│   ├── main.mm
│   ├── MNISTClassifierGraph.h
│   ├── MNISTClassifierGraph.mm
│   └── Controls.h
├── Common/
│   ├── MNISTDataSet.mm
│   ├── DataSources.h
│   ├── DataSources.mm
│   ├── MNISTDataSet.h
│   ├── Helpers.h
│   └── Helpers.mm
├── Configuration/
│   └── SampleCode.xcconfig
└── MPSTrainingHelloWorld.xcodeproj/
    └── .xcodesamplecode.plist

Structure observations

  • Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
  • Primary languages: C/Objective-C header, Objective-C++.
  • The verified tree contains 3 project/configuration file(s) and 4 source declaration(s).

Overall architecture

Reference code

MPSTrainingClassifier/main.mm:156 — architecture anchor

int main(int argc, const char * argv[]) {
    // ...
        gDevice = MTLCreateSystemDefaultDevice();
    // ...
}

Interpretation

The arrows summarize the source-visible entry, role-named types or folders, and framework direction; when nodes come from structural folders, the sequence is a high-level interpretation rather than proof that every adjacent node calls the next. Ownership is claimed only where the next section cites a stored property or assignment. The diagram is intentionally limited to the dominant path into Metal Performance Shaders.

Ownership and state

Ownership evidence

Common/MNISTDataSet.mm:14 — stored dependency or nearest verified ownership anchor

@interface NSData (gunzip)

- (NSData *)gunzippedData;

@end
Owner Object or state Relationship Mutation authority
main Metal Performance Shaders APIs Uses framework types; no stored lifecycle relationship was detected in the architecture anchor. The declaring implementation controls calls.

Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.

Concurrency, scheduling, and thread safety

Evidence limit: actor isolation, async/await, or Task creation does not by itself prove background-thread execution; Sendable conformance alone does not prove thread-safe mutation.

No source-visible execution, scheduling, or synchronization boundary was found in the indexed source.

@MainActor/MainActor.run, DispatchQueue.main, and RunLoop.main are reported as distinct isolation, queue, and event-loop mechanisms. A plain Task is kept separate from Task.detached; neither is labeled as a background thread.

State propagation, frameworks, and dependencies

Evidence limit: an import proves a source-level compilation dependency at the cited line; it does not prove runtime use, architectural adoption, or whether a Swift package is a direct application dependency.

Category Mechanism or module Verified role Evidence
Source import Foundation The cited file imports this module; runtime use and architectural role are not inferred. MPSTrainingClassifier/Controls.h:11
Source import Metal The cited file imports this module; runtime use and architectural role are not inferred. MPSTrainingClassifier/Controls.h:12
Source import MetalPerformanceShaders The cited file imports this module; runtime use and architectural role are not inferred. MPSTrainingClassifier/Controls.h:13
Source import random The cited file imports this module; runtime use and architectural role are not inferred. Common/DataSources.mm:10
Source import zlib.h The cited file imports this module; runtime use and architectural role are not inferred. Common/MNISTDataSet.mm:9

receive(on:) describes downstream delivery scheduling, while subscribe(on:) describes upstream subscription/request/cancel scheduling. An import Combine alone establishes neither behavior nor a Store, reducer, Redux, or other application architecture.

Class and protocol design

Common/DataSources.h:34 — representative type boundary

#ifndef DataSources_h
@interface ConvDataSource : NSObject<MPSCNNConvolutionDataSource>{
    // ...
}
@end    /* ConvDataSource */
#endif /* DataSources_h */
Type Responsibility Depends on or conforms to
ConvDataSource Supplies data through a callback contract NSObject, MPSCNNConvolutionDataSource
NSData Represents feature data Concrete collaborators/imported frameworks
MNISTDataSet Defines a feature-specific type boundary NSObject
MNISTClassifierGraph Defines a feature-specific type boundary NSObject

No local protocol conformance is claimed as protocol-oriented design; external framework conformances are listed only as dependencies.

Access control

Symbol Access Verified effect Likely rationale
ConvDataSource (Common/DataSources.h:34) header-visible The declaration is exposed to translation units that import the header. Inference: declare a contract needed by other Objective-C/C translation units.
NSData (Common/MNISTDataSet.mm:14) implementation Visibility follows header/implementation and language linkage rules. Inference: keep the declaration in the Objective-C implementation boundary.
MNISTDataSet (Common/MNISTDataSet.h:22) header-visible The declaration is exposed to translation units that import the header. Inference: declare a contract needed by other Objective-C/C translation units.
DataSources (Common/DataSources.mm:12) language/file boundary Visibility follows header/implementation and language linkage rules. Inference: the language’s file or module boundary is sufficient for this sample collaboration.

Reference code

Common/DataSources.h:34 — representative boundary

#ifndef DataSources_h
@interface ConvDataSource : NSObject<MPSCNNConvolutionDataSource>{
    // ...
}
@end    /* ConvDataSource */
#endif /* DataSources_h */

Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.

Logic ownership and placement

Logic Owning type or file Placement rationale
Supplies data through a callback contract ConvDataSource The source’s DataSource suffix makes this role explicit.

Design patterns

Pattern Source evidence Purpose or tradeoff
Delegate or data-source callbacks Common/DataSources.h:34 Callback protocols invert event delivery back into the sample’s owner.

Main application flow

Reference code

Common/DataSources.mm:177checkpointWithCommandQueue()

-(void) checkpointWithCommandQueue:(nonnull id<MTLCommandQueue>) commandQueue{
    @autoreleasepool{
        MPSCommandBuffer *commandBuffer = [MPSCommandBuffer commandBufferFromCommandQueue:gCommandQueue];
        [_convWtsAndBias synchronizeOnCommandBuffer:commandBuffer];
        [commandBuffer commit];
        [commandBuffer waitUntilCompleted];
    }
}

Naming conventions

  • Types: DataSource: ConvDataSource.
  • Protocols: no local protocol declaration in the scanned source.
  • Methods: gunzippedData, init, getRandomTrainingBatchWithDevice, initWithKernelWidth, dataType, descriptor, weights, biasTerms.
  • Files: Common/MNISTDataSet.mm, Common/MNISTDataSet.h, MPSTrainingClassifier/MNISTClassifierGraph.h, MPSTrainingClassifier/MNISTClassifierGraph.mm.

Architecture takeaways

  • main is the main source-visible entry or composition anchor for this sample.
  • Framework work reaches Metal, MetalPerformanceShaders, random through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
  • Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
  • Access-control conclusions separate verified language visibility from the likely design rationale.
  • The source does not justify labeling the design protocol-oriented.

Source map

Source file Relevant symbols
MPSTrainingClassifier/main.mm Cited implementation, Feature implementation
Common/MNISTDataSet.mm MNISTDataSet, NSData, zlib.h
Common/DataSources.h ConvDataSource, Cited implementation
Common/MNISTDataSet.h MNISTDataSet
Common/DataSources.mm DataSources, random, ConvDataSource
MPSTrainingClassifier/Controls.h Foundation, Metal, MetalPerformanceShaders, Feature implementation
MPSTrainingClassifier/MNISTClassifierGraph.h MNISTClassifierGraph
MPSTrainingClassifier/MNISTClassifierGraph.mm MNISTClassifierGraph
Common/Helpers.h Feature implementation
Common/Helpers.mm Feature implementation