-
Premiers pas avec MLX pour les puces Apple
MLX est un framework de réseau flexible et efficace pour le calcul numérique et l'apprentissage automatique sur les puces Apple. Nous explorerons les caractéristiques fondamentales, notamment la mémoire unifiée, le calcul paresseux et les transformations de fonctions. Nous examinerons également des techniques plus avancées pour créer et accélérer des modèles d'apprentissage automatique sur les plates-formes d'Apple à l'aide des API Swift et Python.
Chapitres
- 0:00 - Introduction
- 1:15 - Présentation de MLX
- 4:21 - Caractéristiques principales
- 10:15 - Accélération de MLX
- 17:30 - MLX Swift
Ressources
- MLX Swift Examples
- MLX Examples
- MLX Swift
- MLX LM - Python API
- MLX Explore - Python API
- MLX Framework
- MLX Llama Inference
- MLX
Vidéos connexes
WWDC25
-
Rechercher dans cette vidéo…
-
-
3:48 - Basics
import mlx.core as mx # Make an array a = mx.array([1, 2, 3]) # Make another array b = mx.array([4, 5, 6]) # Do an operation c = a + b # Access information about the array shape = c.shape dtype = c.dtype print(f"Result c: {c}") print(f"Shape: {shape}") print(f"Data type: {dtype}") -
5:31 - Unified memory
import mlx.core as mx a = mx.array([1, 2, 3]) b = mx.array([4, 5, 6]) c = mx.add(a, b, stream=mx.gpu) d = mx.multiply(a, b, stream=mx.cpu) print(f"c computed on the GPU: {c}") print(f"d computed on the CPU: {d}") -
6:20 - Lazy computation
import mlx.core as mx # Make an array a = mx.array([1, 2, 3]) # Make another array b = mx.array([4, 5, 6]) # Do an operation c = a + b # Evaluates c before printing it print(c) # Also evaluates c c_list = c.tolist() # Also evaluates c mx.eval(c) print(f"Evaluate c by converting to list: {c_list}") print(f"Evaluate c using print: {c}") print(f"Evaluate c using mx.eval(): {c}") -
7:32 - Function transformation
import mlx.core as mx def sin(x): return mx.sin(x) dfdx = mx.grad(sin) def sin(x): return mx.sin(x) d2fdx2 = mx.grad(mx.grad(mx.sin)) # Computes the second derivative of sine at 1.0 d2fdx2(mx.array(1.0)) -
9:16 - Neural Networks in MLX
import mlx.core as mx import mlx.nn as nn import mlx.optimizers as optim class MLP(nn.Module): """A simple MLP.""" def __init__(self, dim, h_dim): super().__init__() self.linear1 = nn.Linear(dim, h_dim) self.linear2 = nn.Linear(h_dim, dim) def __call__(self, x): x = self.linear1(x) x = nn.relu(x) x = self.linear2(x) return x -
9:57 - MLX and PyTorch
# MLX version import mlx.core as mx import mlx.nn as nn import mlx.optimizers as optim class MLP(nn.Module): """A simple MLP.""" def __init__(self, dim, h_dim): super().__init__() self.linear1 = nn.Linear(dim, h_dim) self.linear2 = nn.Linear(h_dim, dim) def __call__(self, x): x = self.linear1(x) x = nn.relu(x) x = self.linear2(x) return x # PyTorch version import torch import torch.nn as nn import torch.optim as optim class MLP(nn.Module): """A simple MLP.""" def __init__(self, dim, h_dim): super().__init__() self.linear1 = nn.Linear(dim, h_dim) self.linear2 = nn.Linear(h_dim, dim) def forward(self, x): x = self.linear1(x) x = x.relu() x = self.linear2(x) return x -
11:35 - Compiling MLX functions
import mlx.core as mx import math def gelu(x): return x * (1 + mx.erf(x / math.sqrt(2))) / 2 @mx.compile def compiled_gelu(x): return x * (1 + mx.erf(x / math.sqrt(2))) / 2 x = mx.random.normal(shape=(4,)) out = gelu(x) compiled_out = compiled_gelu(x) print(f"gelu: {out}") print(f"compiled gelu: {compiled_out}") -
12:32 - MLX Fast package
import mlx.core as mx import time def rms_norm(x, weight, eps=1e-5): y = x.astype(mx.float32) y = y * mx.rsqrt(mx.mean( mx.square(y), axis=-1, keepdims=True, ) + eps) return (weight * y).astype(x.dtype) batch_size = 8192 feature_dim = 4096 iterations = 1000 x = mx.random.normal([batch_size, feature_dim]) weight = mx.ones(feature_dim) bias = mx.zeros(feature_dim) start_time = time.perf_counter() for _ in range(iterations): y = rms_norm(x, weight, eps=1e-5) mx.eval(y) rms_norm_time = time.perf_counter() - start_time print(f"rms_norm execution: {gelu_time:0.4f} sec") start_time = time.perf_counter() for _ in range(iterations): mx.eval(mx.fast.rms_norm(x, weight, eps=1e-5)) fast_rms_norm_time = time.perf_counter() - start_time print(f"mx.fast.rms_norm execution: {compiled_gelu_time:0.4f} sec") print(f"mx.fast.rms_norm speedup: {rms_norm_time/fast_rms_norm_time:0.2f}x") -
13:30 - Custom Metal kernel
import mlx.core as mx # Build the kernel source = """ uint elem = thread_position_in_grid.x; out[elem] = metal::exp(inp[elem]); """ kernel = mx.fast.metal_kernel( name="myexp", input_names=["inp"], output_names=["out"], source=source, ) # Call the kernel on a sample input x = mx.array([1.0, 2.0, 3.0]) out = kernel( inputs=[x], grid=(x.size, 1, 1), threadgroup=(256, 1, 1), output_shapes=[x.shape], output_dtypes=[x.dtype], )[0] print(out) -
14:41 - Quantization
import mlx.core as mx x = mx.random.normal([1024]) weight = mx.random.normal([1024, 1024]) quantized_weight, scales, biases = mx.quantize( weight, bits=4, group_size=32, ) y = mx.quantized_matmul( x, quantized_weight, scales=scales, biases=biases, bits=4, group_size=32, ) w_orig = mx.dequantize( quantized_weight, scales=scales, biases=biases, bits=4, group_size=32, ) -
15:23 - Quantized models
import mlx.nn as nn model = nn.Sequential( nn.Embedding(100, 32), nn.Linear(32, 32), nn.Linear(32, 32), nn.Linear(32, 1), ) print(model) nn.quantize( model, bits=4, group_size=32, ) print(model) -
16:50 - Distributed
import mlx.core as mx group = mx.distributed.init() world_size = group.size() rank = group.rank() x = mx.array([1.0]) x_sum = mx.distributed.all_sum(x) print(x_sum) -
17:20 - Distributed launcher
mlx.launch --hosts ip1, ip2, ip3, ip4 my_script.py -
18:20 - MLX Swift
// Swift import MLX // Make an array let a = MLXArray([1, 2, 3]) // Make another array let b = MLXArray([1, 2, 3]) // Do an operation let c = a + b // Access information about the array let shape = c.shape let dtype = c.dtype // Print results print("a: \(a)") print("b: \(b)") print("c = a + b: \(c)") print("shape: \(shape)") print("dtype: \(dtype)")
-
-
- 0:00 - Introduction
MLX est un framework open source optimisé pour les puces Apple. Il permet d’effectuer des tâches d’apprentissage automatique efficaces et d’exécuter de grands modèles de langage directement sur l’appareil à l’aide de Python et de Swift.
- 1:15 - Présentation de MLX
Ce framework d’apprentissage automatique hautes performances est optimisé pour les puces Apple, ce qui permet d’effectuer des tâches rapides de calcul numérique et d’apprentissage automatique sur le processeur principal et le processeur graphique. Il possède une API de base de type NumPy, et l’API de niveau supérieur est similaire à PyTorch et JAX. Utilisez-le dans des apps comme LM Studio pour générer du texte sur l’appareil avec de grands modèles de langage. MLX possède des API en Python, Swift, C++ et C. MLX est open-source sous licence MIT et dispose d’une communauté active sur Hugging Face.
- 4:21 - Caractéristiques principales
MLX est incroyablement efficace, car il est conçu pour les puces Apple et s’appuie sur son architecture de mémoire unifiée. Le partage de la mémoire entre le processeur principal et le processeur graphique rend inutile la copie des données ; les opérations spécifient simplement l’appareil souhaité. Au lieu d’exécuter immédiatement un calcul, MLX construit des graphiques de calcul qui ne sont exécutés que lorsqu’un résultat est nécessaire. Grâce aux transformations de fonctions, MLX peut prendre des fonctions en entrée et en renvoyer de nouvelles, ce qui facilite la différenciation automatique et d’autres optimisations. MLX comprend des paquets de niveau supérieur pour la création et l’entraînement de réseaux neuronaux, ainsi que des opérations courantes d’apprentissage automatique. Ces paquets sont modulaires et conçus pour être similaires aux frameworks populaires comme PyTorch, ce qui facilite le changement pour les développeurs.
- 10:15 - Accélération de MLX
Les compilations de fonctions avec « mx.compile » fusionnent plusieurs lancements de noyau GPU en un seul noyau, réduisant ainsi la bande passante mémoire et la surcharge d’exécution. Pour les opérations plus complexes, le sous-paquet « mx.fast » fournit des implémentations spécialisées et hautement optimisées des opérations courantes d’apprentissage automatique, telles que la norme RMS et les mécanismes d’attention. MLX permet la quantification pour une inférence plus rapide et plus efficace avec moins de surcharge de mémoire, réduisant ainsi la précision sans trop affecter la qualité. Les calculs à grande échelle peuvent utiliser le sous-paquet « mx.distributed » pour répartir le travail sur plusieurs machines.
- 17:30 - MLX Swift
MLX propose également une API Swift qui offre les mêmes améliorations en termes d’efficacité, pour un développement transparent sur les plateformes Apple dans Xcode. Visitez le site web de MLX ou téléchargez les référentiels exemple pour commencer et en savoir plus.