| name | apple-silicon |
| description | Apple Silicon optimization for VMs, ML inference, and compression. Covers Metal GPU acceleration, MLX model inference, CoreML conversion, M-series zstd compression, Apple Virtualization Framework, and performance tuning. |
| author | gastown |
| version | 1.0.0 |
Apple Silicon Optimization Skill
Comprehensive guide for optimizing applications on Apple Silicon (M1/M2/M3/M4) including GPU acceleration, ML inference, virtualization, and compression.
Overview
Apple Silicon's unified memory architecture and specialized hardware enable significant performance gains when properly optimized:
| Component | Capability | Use Case |
|---|
| Neural Engine | 16+ TOPS | Quantized model inference |
| Metal GPU | Up to 76 cores | Vector search, embeddings |
| Unified Memory | Up to 192GB | Large model loading |
| ProRes Engine | Hardware decode | Media processing |
Metal GPU Acceleration
Check Metal Availability
import { metalAccelerator, isMetalAvailable, getMLCapabilities } from '@/lib/ml/metal-accelerator';
const available = await isMetalAvailable();
const info = await getMLCapabilities();
console.log(`Device: ${info.name}`);
console.log(`Neural Engine: ${info.neuralEngineAvailable}`);
console.log(`Metal: ${info.metalAvailable}`);
console.log(`Max memory: ${info.recommendedMaxWorkingSetSize / 1024 / 1024 / 1024}GB`);
GPU-Accelerated Vector Search
import { metalAccelerator, search } from '@/lib/ml/metal-accelerator';
await metalAccelerator.initialize();
const queryEmbedding = await metalAccelerator.generateEmbedding("search query");
const results = await search(queryEmbedding, vectorDatabase, 10);
const batchResults = await metalAccelerator.vectorSearchBatch(
[query1, query2, query3],
vectors,
10
);
Streaming Text Generation
import { metalAccelerator } from '@/lib/ml/metal-accelerator';
for await (const token of metalAccelerator.generateText("Explain quantum computing", {
model: 'mistral-7b-int8',
maxTokens: 512,
temperature: 0.7,
})) {
process.stdout.write(token);
}
MLX Model Inference
MLX is Apple's native ML framework optimized for unified memory architecture.
Initialize MLX Provider
import { mlxProvider, isMLXAvailable } from '@/lib/ml/mlx-provider';
const available = await isMLXAvailable();
await mlxProvider.initialize();
const info = await mlxProvider.getSystemInfo();
console.log(`Device: ${info.deviceName}`);
console.log(`Unified Memory: ${info.unifiedMemory / 1024 / 1024 / 1024}GB`);
console.log(`MLX Version: ${info.mlxVersion}`);
Load and Run Models
import { mlxProvider } from '@/lib/ml/mlx-provider';
await mlxProvider.loadModel({
name: 'mlx-community/Mistral-7B-Instruct-v0.3-4bit',
quantization: 'int4',
maxContextLength: 4096,
device: 'auto'
});
const result = await mlxProvider.generateText("Write a haiku about coding", {
maxTokens: 100,
temperature: 0.8,
});
console.log(result.text);
console.log(`${result.metrics.tokensPerSecond} tokens/sec`);
Streaming Generation
import { mlxProvider } from '@/lib/ml/mlx-provider';
for await (const token of mlxProvider.generateTextStream(prompt, options)) {
process.stdout.write(token.token);
}
Embedding Generation
import { mlxProvider, generateEmbedding, generateEmbeddingsBatch } from '@/lib/ml/mlx-provider';
const embedding = await generateEmbedding("Hello world");
const embeddings = await generateEmbeddingsBatch([
"First document",
"Second document",
"Third document"
], { batchSize: 32 });
const queryEmb = await mlxProvider.generateRAGEmbedding("search query", true);
const docEmb = await mlxProvider.generateRAGEmbedding("document text", false);
RAG Answer Generation
import { mlxProvider } from '@/lib/ml/mlx-provider';
const answer = await mlxProvider.generateRAGAnswer(
"What is the capital of France?",
[
"Paris is the capital and largest city of France.",
"France is a country in Western Europe."
],
{ temperature: 0.3 }
);
CoreML Model Conversion
Convert models from PyTorch/TensorFlow to CoreML for optimized on-device inference.
Install coremltools
pip install coremltools
pip install coremltools==9.0b1
Convert PyTorch Model
import coremltools as ct
import torch
model = YourModel()
model.eval()
example_input = torch.randn(1, 3, 224, 224)
traced_model = torch.jit.trace(model, example_input)
mlmodel = ct.convert(
traced_model,
inputs=[ct.TensorType(shape=example_input.shape)],
minimum_deployment_target=ct.target.iOS17
)
mlmodel.save("model.mlpackage")
Quantize for Performance
from coremltools.optimize.coreml import linear_quantize_weights, palettize_weights
quantized = linear_quantize_weights(mlmodel, mode="linear_symmetric", dtype="int4")
palettized = palettize_weights(mlmodel, nbits=4)
Convert Embedding Models
import coremltools as ct
import torch
import numpy as np
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
class EmbeddingWrapper(torch.nn.Module):
def __init__(self, model):
super().__init__()
self.model = model
def forward(self, input_ids, attention_mask):
outputs = self.model({'input_ids': input_ids, 'attention_mask': attention_mask})
return outputs['sentence_embedding']
wrapper = EmbeddingWrapper(model)
wrapper.eval()
traced = torch.jit.trace(wrapper, (
torch.randint(0, 30522, (1, 128)),
torch.ones(1, 128, dtype=torch.long)
))
mlmodel = ct.convert(
traced,
inputs=[
ct.TensorType(name="input_ids", shape=(1, 128), dtype=np.int32),
ct.TensorType(name="attention_mask", shape=(1, 128), dtype=np.int32)
],
minimum_deployment_target=ct.target.iOS16
)
LLM Conversion with KV-Cache (macOS 15+)
import coremltools as ct
import numpy as np
mlmodel = ct.convert(
traced_llm,
inputs=[ct.TensorType(shape=(1, seq_len), dtype=np.int32)],
states=[
ct.StateType(
wrapped_type=ct.TensorType(shape=(1, 32, 2048, 128)),
name="kv_cache"
)
],
minimum_deployment_target=ct.target.macOS15
)
M-Series zstd Compression
Apple Silicon's hardware acceleration benefits zstd compression.
Optimal Settings for M-Series
zstd -1 -T0 file.tar
zstd -3 -T0 file.tar
zstd -19 -T0 file.tar
zstd --ultra -22 --long=31 -T0 file.tar
Programmatic Usage
import { spawn } from 'child_process';
async function compressWithZstd(input: string, output: string, level = 3): Promise<void> {
return new Promise((resolve, reject) => {
const zstd = spawn('zstd', [
`-${level}`,
'-T0',
'--rm',
'-o', output,
input
]);
zstd.on('close', (code) => code === 0 ? resolve() : reject(new Error(`zstd failed: ${code}`)));
});
}
await compressWithZstd('alpine.raw', 'alpine.raw.zst', 19);
Performance Benchmarks (M1 Max)
| Level | Speed | Ratio | Use Case |
|---|
| -1 | 500 MB/s | 2.5x | Real-time streaming |
| -3 | 200 MB/s | 3.0x | General purpose |
| -9 | 80 MB/s | 3.3x | Distribution |
| -19 | 15 MB/s | 3.5x | Archive |
| -22 --ultra | 5 MB/s | 3.7x | Maximum compression |
Apple Virtualization Framework
Native VM support using Apple's Virtualization.framework.
Basic VM Configuration (Swift)
import Virtualization
let config = VZVirtualMachineConfiguration()
config.cpuCount = 4
config.memorySize = 4 * 1024 * 1024 * 1024
let bootLoader = VZLinuxBootLoader(kernelURL: kernelURL)
bootLoader.commandLine = "console=hvc0 root=/dev/vda"
config.bootLoader = bootLoader
let diskAttachment = try VZDiskImageStorageDeviceAttachment(
url: diskURL,
readOnly: false
)
config.storageDevices = [VZVirtioBlockDeviceConfiguration(attachment: diskAttachment)]
let networkAttachment = VZNATNetworkDeviceAttachment()
config.networkDevices = [VZVirtioNetworkDeviceConfiguration(attachment: networkAttachment)]
let vm = VZVirtualMachine(configuration: config)
try await vm.start()
Apple Container Runtime (macOS 26+)
curl -L -o container.pkg \
"https://github.com/apple/container/releases/download/0.9.0/container-0.9.0-installer-signed.pkg"
sudo installer -pkg container.pkg -target /
container system start
container run -d --name web -p 8080:80 nginx:latest
container inspect web --format '{{.NetworkSettings.IPAddress}}'
container run --memory 2g --cpus 2 myapp:latest
container build -t myapp:latest .
container push myapp:latest ghcr.io/org/myapp:latest
Lima/vfkit VM Management
limactl create --vm-type=vz --cpus=4 --memory=8 --name=dev
limactl start dev
limactl shell dev
limactl create --mount-writable --mount=/Users:/Users dev
Performance Tuning
Memory Optimization
const memory = await mlxProvider.getMemoryUsage();
console.log(`Used: ${memory.used / 1024 / 1024}MB`);
console.log(`Model: ${memory.modelMemory / 1024 / 1024}MB`);
console.log(`Cache: ${memory.cacheMemory / 1024 / 1024}MB`);
await mlxProvider.clearCache();
Model Selection by Device
| Device | Recommended Models | Max Model Size |
|---|
| M1 (8GB) | 7B-int4, embeddings | ~4GB |
| M1 Pro (16GB) | 7B-int8, 13B-int4 | ~10GB |
| M1 Max (32GB) | 13B-int8, 30B-int4 | ~24GB |
| M1 Ultra (64GB) | 30B-int8, 70B-int4 | ~48GB |
| M2/M3/M4 variants | Same + 10-20% faster | Same |
Inference Performance Targets
| Model | Device | Target Speed |
|---|
| Embedding (384d) | M1 | <50ms |
| 7B-int4 | M1 Max | 30-40 tok/s |
| 7B-int8 | M1 Max | 20-25 tok/s |
| 13B-int4 | M1 Ultra | 25-30 tok/s |
| 70B-int4 | M1 Ultra | 10-15 tok/s |
Power Management
sudo powermetrics --samplers smc -n 1
sudo powermetrics --samplers gpu_power -n 1
sudo powermetrics --samplers ane_power -n 1
Datadog Integration
Track MLX operations with distributed tracing.
import { mlxTracedProvider, traceMLXOperation } from '@/lib/ml/mlx-ddtrace';
const result = await mlxTracedProvider.generateText(prompt, options, {
tags: { 'user.id': userId },
sessionId: sessionId
});
await traceMLXOperation('custom_inference', async () => {
}, { 'model.name': 'custom-model' });
Best Practices
Do
- Use INT4 quantization for LLMs - 4x smaller with <5% quality loss
- Batch embeddings - significantly faster than one-by-one
- Enable unified memory - let MLX manage memory allocation
- Use streaming - better UX for text generation
- Monitor memory - prevent OOM with large models
Avoid
- FP32 models - waste memory, no accuracy benefit
- Small batch sizes - underutilize GPU
- Excessive model switching - loading is expensive
- Ignoring thermal throttling - sustained loads may slow down
Files
| Path | Description |
|---|
src/lib/ml/metal-accelerator.ts | Metal GPU acceleration API |
src/lib/ml/mlx-provider.ts | MLX model inference |
src/lib/ml/mlx-ddtrace.ts | Datadog tracing for MLX |
docs/research/apple-coremltools-integration.md | CoreML conversion research |
docs/research/apple-containerization-integration.md | Containerization research |
docs/research/apple-container-runtime-integration.md | Container runtime research |
References