Inférence Core ML sur appareil : les patrons qui passent réellement en production
Core ML est le moteur d’inférence sur appareil livré avec chaque appareil Apple moderne. Le framework dispatche vers le Neural Engine lorsque celui-ci est disponible, vers le GPU sinon, et vers le CPU en dernier recours, en choisissant automatiquement le chemin le plus rapide en fonction du modèle et du matériel1. Le résultat sur un iPhone récent : une inférence avec une latence allant de la sous-milliseconde à quelques dizaines de millisecondes pour la plupart des tailles de modèles en production, gratuite par appel, sans aller-retour réseau et sans exposition de données à des tiers.
La réputation du framework comme « tuyauterie obscure » est dépassée. Core ML alimente désormais le LLM sur appareil d’Apple Intelligence, la recherche sémantique de l’app Photos, la reconnaissance de scène de l’app Appareil photo, et la plupart des apps tierces qui livrent du ML local. Les patrons qui font qu’un déploiement Core ML passe réellement en production, plutôt que de simplement « fonctionner sur ma machine », forment un petit ensemble : conversion de modèle, indication de dispatch, budget de latence et quantification. Le billet parcourt chacun d’entre eux à la lumière de la documentation Apple.
TL;DR
- Core ML exécute des fichiers
.mlpackageet.mlmodelsur le Neural Engine, le GPU et le CPU d’Apple Silicon. Le dispatch est automatique mais peut être suggéré viaMLModelConfiguration.computeUnits2. - La conversion de modèle se fait à travers
coremltools(PyTorch, TensorFlow, ONNX → Core ML). La conversion est une tâche d’outillage, pas une tâche d’exécution ; une fois qu’un modèle est converti et empaqueté, l’app le charge et l’exécute. - L’architecture à mémoire unifiée d’Apple Silicon signifie que les poids du modèle ne sont pas copiés entre CPU, GPU et NE ; la même mémoire sous-tend les trois3. Ce détail architectural est ce qui rend possible une inférence à la sous-milliseconde.
- La quantification (INT8, INT4 dans les versions récentes de Core ML) réduit la taille du modèle et accélère l’inférence sur le Neural Engine, avec un coût mesurable en précision qui dépend du modèle.
- Le lien avec les flux de travail d’agents : Foundation Models (le LLM sur appareil d’Apple Intelligence) est livré comme un modèle Core ML derrière une API Swift de haut niveau ; les mêmes patrons de dispatch et de quantification s’appliquent.
Le modèle mental : trois chemins de calcul, une mémoire
Apple Silicon (Mac de la série M et iPhone de la série A à partir de l’A12 Bionic) propose trois cibles d’inférence :
Neural Engine. Un accélérateur spécialisé pour la multiplication matricielle à faible précision. Le plus rapide pour les opérations dont dépendent les modèles ML modernes (convolutions, attention, embeddings). Consommation d’énergie la plus faible. Limité à des types d’opérations et des formes de tenseurs spécifiques ; les opérations non prises en charge basculent sur le GPU ou le CPU couche par couche.
GPU. Calcul parallèle à usage général via Metal. Plus lent que le Neural Engine pour le travail de forme ML mais plus rapide que le CPU. Gère les opérations que le Neural Engine ne prend pas en charge.
CPU. Le repli. Lent pour l’inférence ML, mais toujours disponible, prend toujours en charge toutes les opérations, et prévisible.
L’architecture à mémoire unifiée signifie que la même RAM physique sous-tend les trois3. Les poids d’un modèle, chargés une seule fois, ne sont pas copiés lorsque le dispatch passe d’une cible à l’autre. Ce fait architectural transforme le dispatch multi-cible d’un coût de copie par couche en une décision d’ordonnancement par couche.
MLModelConfiguration.computeUnits contrôle le dispatch :
let config = MLModelConfiguration()
config.computeUnits = .all // default: NE, GPU, CPU
// Other options:
// .cpuAndGPU
// .cpuAndNeuralEngine
// .cpuOnly
let model = try MyModel(configuration: config)
.all est la valeur par défaut et le bon choix pour presque toutes les apps. Le framework choisit le chemin le plus rapide par opération, et la décision par opération est plus rapide que toute heuristique que le développeur écrirait. La rare raison de surcharger est de forcer .cpuOnly pour tester la parité (un modèle se comporte différemment sur des chemins différents et le test veut le chemin déterministe) ou de forcer .cpuAndGPU pour libérer le Neural Engine pour une autre tâche concurrente.
Conversion de modèle : la tâche d’outillage
La plupart des modèles ML sont entraînés dans PyTorch, TensorFlow ou directement via Create ML d’Apple. Core ML accepte les fichiers .mlpackage, le format moderne introduit dans Xcode 13 qui remplace l’ancien .mlmodel4. La conversion se fait à travers coremltools, le paquet Python open source d’Apple5.
Une conversion typique de PyTorch vers Core ML suit trois étapes :
- Charger le modèle PyTorch entraîné et le placer en mode inférence.
- Tracer le modèle avec un tenseur d’entrée d’exemple correspondant à la forme d’entrée de production.
- Convertir le modèle tracé avec
coremltoolsciblant une version iOS de déploiement.
import torch
import coremltools as ct
model = MyTrainedModel()
model.load_state_dict(torch.load("weights.pth"))
example_input = torch.rand(1, 3, 224, 224)
traced_model = torch.jit.trace(model, example_input)
mlmodel = ct.convert(
traced_model,
inputs=[ct.ImageType(name="image", shape=example_input.shape)],
minimum_deployment_target=ct.target.iOS18,
compute_units=ct.ComputeUnit.ALL,
)
mlmodel.save("MyModel.mlpackage")
La conversion se fait une seule fois, dans un environnement de développement, ciblant une version iOS de déploiement (minimum_deployment_target). Le .mlpackage produit est ce qui est ensuite déposé dans le projet Xcode. L’app à l’exécution n’exécute pas coremltools.
Deux pièges pratiques en conversion. Premièrement, les entrées à forme dynamique nécessitent une gestion explicite via ct.RangeDim parce que la valeur par défaut à forme statique de Core ML produit des erreurs peu utiles lorsque l’app de production fournit des tailles d’entrée variables. Deuxièmement, les ops personnalisées en PyTorch qui n’ont pas d’équivalent Core ML nécessitent soit une couche personnalisée Core ML (du code Swift qui exécute l’op manquante) soit un changement d’architecture du modèle pour retirer l’op avant la conversion. Les deux sont bien documentés5.
Des budgets de latence qui s’appliquent réellement
Trois budgets de latence comptent pour les apps en production :
16 ms (UI en direct à 60 fps). Un filtre de caméra en temps réel, une scène AR qui se met à jour image par image, un analyseur audio en direct. Le budget inclut tout : prétraitement de l’image, inférence du modèle, post-traitement, mise à jour de l’UI. Les modèles qui s’y conforment sont typiquement petits (classe MobileNetV3, moins de 100 M de paramètres) et tournent sur le Neural Engine.
100 ms (UI interactive). Un utilisateur effectue une action et attend le résultat : appuyer pour identifier, dessiner pour reconnaître, dicter pour transcrire. Le budget est plus indulgent et accepte des modèles plus grands. Les modèles de langage de moins d’un milliard de paramètres, les petits transformeurs de vision et la plupart des classificateurs de qualité production s’y inscrivent confortablement.
1 s ou plus (en arrière-plan ou par lot). Indexation de la photothèque, analyse de documents, préchauffage du modèle au lancement de l’app. Des modèles plus grands fonctionnent, mais l’attente de l’utilisateur doit être gérée avec un indicateur de progression. Le LLM sur appareil de Foundation Models réside ici pour les opérations à plus large fenêtre de contexte.
Les budgets sont des indications, pas des limites strictes. Le bon mouvement est de mesurer sur un appareil cible avec os_signpost ou le modèle Core ML d’Instruments6 plutôt que de faire confiance à des chiffres théoriques venant d’une autre machine.
Quantification : quand plus petit signifie plus rapide
Core ML prend en charge plusieurs niveaux de quantification7 :
- Float32 (précision complète). Le défaut d’entraînement. Le plus volumineux, le plus précis, le plus lent.
- Float16. Demi-précision. Plus petit et plus rapide sur GPU et NE ; la perte de précision est habituellement négligeable pour des modèles bien conditionnés.
- INT8. Quantification entière sur 8 bits avec calibration. Environ 4 fois plus petit que le Float32, souvent 2 à 4 fois plus rapide sur le NE. La perte de précision varie ; pour les modèles de vision, une perte de précision top-1 sous le 1 % est atteignable avec un entraînement conscient de la quantification.
- INT4 et en dessous. Quantification agressive que les versions récentes de Core ML prennent en charge pour des architectures de modèles spécifiques (LLMs, grands modèles de vision). Une perte de précision significative est le compromis ; la technique fonctionne mieux lorsqu’elle est associée à un entraînement conscient de la quantification spécifique au modèle.
La configuration de quantification linéaire via coremltools.optimize.coreml.linear_quantize_weights accepte une configuration d’op globale qui choisit le mode de quantification (linear_symmetric ou linear) et un seuil de taille de poids en dessous duquel les poids restent en précision complète. La conversion s’exécute sur un .mlpackage existant et produit un nouveau paquet quantifié ; les deux peuvent être livrés côte à côte dans le bundle, l’app choisissant lequel charger en fonction de la classe d’appareil.
La décision de quantification est propre à chaque modèle : un petit classificateur peut ne pas en bénéficier parce que son calcul est déjà bon marché ; un grand modèle de langage en bénéficie énormément parce que son calcul est dominé par des multiplications matricielles sur les poids quantifiés. La bonne approche est de quantifier, mesurer la précision sur un jeu de test mis de côté, et livrer si l’impact sur la précision est acceptable pour le cas d’usage.
Les modèles intégrés d’Apple à brancher directement
Apple livre plusieurs modèles Core ML pré-entraînés via la page Core ML Models8. Catégories à connaître :
- Classification d’images : MobileNetV2, ResNet50, variantes de SqueezeNet, toutes empaquetées et prêtes à être branchées dans une
VNCoreMLRequestdu framework Vision. - Détection d’objets : YOLOv3, MNIST, variantes de CenterNet.
- Estimation de pose : PoseNet pour la pose corporelle (une alternative de référence à la
VNDetectHumanBodyPoseRequestde Vision). - Segmentation sémantique : DeepLabV3 pour la segmentation d’image.
- Reconnaissance de texte : alternatives OCR basées sur le ML à celle intégrée à Vision.
Pour la plupart des apps, les modèles pré-entraînés d’Apple couvrent les primitives de perception (classer, détecter, segmenter) sans nécessiter d’entraînement personnalisé. Le LLM sur appareil de Foundation Models (couvert dans Foundation Models on-device LLM) en est l’exemple le plus volumineux : un LLM de plusieurs milliards de paramètres livré comme un modèle Core ML derrière une API Swift de haut niveau, dispatché sur le Neural Engine, disponible hors ligne.
Chiffrement de modèle et considérations App Store
Un .mlpackage dans le bundle de l’app est lisible par quiconque décompresse l’IPA. Pour les modèles qui représentent une propriété intellectuelle significative, Apple prend en charge le chiffrement de modèle via le flux Encrypt your Core ML model9 : une clé de chiffrement est générée via Xcode et gérée via CloudKit, le modèle dans le bundle est chiffré, et Core ML déchiffre au chargement.
Pour la plupart des apps, le chiffrement est superflu. Un modèle entraîné sur des données ImageNet banalisées n’est pas un facteur de différenciation concurrentiel ; le chiffrer ajoute de la complexité opérationnelle sans rien protéger de précieux. Réservez le chiffrement aux modèles qui représentent un véritable investissement en données d’entraînement ou un avantage concurrentiel.
Confidentialité sur appareil : la victoire architecturale
L’argument de confidentialité est direct. L’inférence Core ML se déroule entièrement sur l’appareil. Les données d’entrée (images, audio, texte) ne quittent pas l’appareil. Le fichier modèle est local ; l’inférence est locale ; le résultat est local.
Pour les apps dans des secteurs réglementés (santé, finance, éducation), ce fait architectural élimine toute une catégorie de travail de conformité. Il n’y a pas de processeur de données tiers à ajouter à une politique de confidentialité. Il n’y a pas de point de terminaison d’API de modèle à valider pour la sécurité. Il n’y a pas de question de résidence des données puisque les données ne se déplacent jamais.
Le format Privacy Manifest10 codifie l’argument de confidentialité pour la soumission App Store : une app qui utilise Core ML pour l’inférence sur appareil et rien d’autre peut déclarer un partage de données tiers nul pour le chemin d’inférence. Le processus de soumission est plus rapide, l’examen de confidentialité plus court, et l’étiquette nutritionnelle de confidentialité visible par l’utilisateur plus propre.
Le lien avec les flux de travail d’agents
Core ML s’associe à trois patrons que la série a déjà couverts :
VNCoreMLRequest du framework Vision. Les modèles Core ML personnalisés s’exécutent via le pipeline Vision avec un prétraitement automatique. Le patron (couvert dans Vision Framework) est la bonne façon de livrer un classificateur ou détecteur d’images personnalisé à l’intérieur d’une app iOS.
LLM sur appareil de Foundation Models. Le LLM d’Apple Intelligence est un modèle Core ML derrière une API Swift de haut niveau. Les mêmes patrons de dispatch (Neural Engine en premier), de quantification (INT4 pour les poids du LLM) et de budget de latence (sous-seconde pour les courtes générations) s’appliquent. Le billet sur Foundation Models couvre l’API ; ce billet couvre le moteur sous-jacent.
Outils App Intents utilisant le ML local. Un AppIntent qui exécute un classificateur d’images ou de texte local renvoie des résultats structurés à Apple Intelligence sans aller-retour réseau. La combinaison est ce qui rend « l’Apple agentique » réellement privée ; les outils de l’agent s’exécutent localement parce que le framework le permet.
Quand l’inférence dans le cloud est le bon choix
Le plafond de Core ML est le calcul de l’appareil. Trois cas où le cloud est correct :
Modèles trop volumineux pour être livrés dans un bundle. Un LLM de 70 milliards de paramètres ne tient pas dans un bundle d’app. Pour des charges de travail à cette échelle, l’inférence dans le cloud (ou sur appareil via streaming des poids, un patron différent) est le bon outil.
État partagé entre appareils pendant l’inférence. Des modèles qui doivent lire ou écrire dans une base de données partagée pendant l’inférence (systèmes de recommandation avec filtrage collaboratif sur des milliards d’enregistrements). Le modèle purement local de Core ML ne convient pas.
Itération rapide du modèle. Une équipe qui livre des mises à jour de modèle quotidiennement bénéficie de l’inférence côté serveur parce que les déploiements ne nécessitent pas de cycles de revue App Store. Le patron « modèle empaqueté dans l’app » de Core ML ajoute de la friction à la cadence de révision du modèle ; le compromis est réel.
Le patron : le cloud gagne sur l’échelle et la vitesse d’itération ; Core ML gagne sur la latence, le coût et la confidentialité.
Ce que ce patron signifie pour les apps iOS 26+
Trois enseignements.
-
Optez par défaut pour Core ML pour tout modèle qui tient dans le bundle et produit un résultat par appel sur lequel l’utilisateur peut agir. Classification d’images, détection d’objets, classification audio, reconnaissance de gestes, génération d’embeddings, tâches de langage de petite à moyenne taille. Le dispatch automatique du framework et le NPU d’Apple Silicon produisent une inférence de la sous-milliseconde à quelques dizaines de millisecondes, gratuitement.
-
Quantifiez agressivement quand l’impact sur la précision est acceptable. L’INT8 est habituellement sûr ; l’INT4 est approprié pour les grands modèles où les économies de taille comptent. Mesurez la précision sur un jeu mis de côté plutôt que de faire confiance à une supposée innocuité universelle de la quantification.
-
Associez avec Vision et Foundation Models pour des pipelines locaux complets. Core ML est le moteur ; Vision est l’API de perception au-dessus ; Foundation Models est le LLM au-dessus. Le billet sur Vision et le billet sur Foundation Models de la série couvrent les surfaces de plus haut niveau.
La série complète Apple Ecosystem : les App Intents typés ; les serveurs MCP ; la question du routage ; Foundation Models ; la distinction LLM d’exécution vs d’outillage ; les trois surfaces ; le patron de source unique de vérité ; Two MCP Servers ; les hooks pour le développement Apple ; les Live Activities ; le contrat d’exécution watchOS ; les internes de SwiftUI ; le modèle mental spatial de RealityKit ; la discipline de schéma SwiftData ; les patrons Liquid Glass ; la livraison multi-plateforme ; la matrice des plateformes ; le framework Vision ; les Symbol Effects ; ce que je refuse d’écrire. Le hub se trouve dans la série Apple Ecosystem. Pour un contexte plus large iOS-avec-agents-IA, voyez le guide iOS Agent Development.
FAQ
Comment Core ML décide-t-il entre Neural Engine, GPU et CPU ?
Core ML examine chaque opération du graphe du modèle et la dispatche vers la cible la plus rapide qui prend en charge l’opération. Le Neural Engine gère les opérations prises en charge (la plupart des multiplications matricielles, convolutions, attention) à la latence et à la consommation les plus basses. Le GPU gère les ops que le NE ne prend pas en charge. Le CPU gère le reste. La décision est par opération, automatique, et plus rapide qu’une heuristique écrite à la main.
Devrais-je toujours utiliser .computeUnits = .all ?
Presque toujours. Le dispatch automatique du framework est bien réglé. Surchargez avec .cpuOnly lors d’un test de parité de sortie (le même modèle renvoie des résultats légèrement différents sur NE et sur CPU à cause de l’arrondi en virgule flottante) ou avec .cpuAndGPU pour libérer le Neural Engine pour une tâche concurrente.
Quelle est la différence pratique entre .mlpackage et .mlmodel ?
.mlpackage est le format moderne introduit dans Xcode 13. Il prend en charge les métadonnées stockées, plusieurs variantes de modèle pour la compilation ML Program (mlprogram) et la chaîne d’outils post-iOS 13. .mlmodel est le format hérité. Les deux se chargent toujours via MLModel ; les nouveaux développements devraient utiliser .mlpackage.
Quelle taille peut atteindre un modèle Core ML dans un bundle d’app ?
Il n’y a pas de limite fixe, mais les tailles de bundle App Store sont plafonnées à 4 Go pour le téléchargement et ont des limites pratiques pour l’installation par voie hertzienne. Le LLM sur appareil de Foundation Models pèse environ 3 Go et est distribué par l’OS plutôt que par le bundle de l’app. Pour les modèles intégrés à l’app, moins de 100 Mo est confortable ; 100 à 500 Mo est faisable avec une stratégie de chargement au démarrage ; plus de 500 Mo se gère mieux via un téléchargement en arrière-plan BGProcessingTask ou des ressources à la demande.
Comment savoir si la quantification a nui à la précision de mon modèle ?
Mettez un jeu de test de côté, exécutez l’inférence sur le modèle Float32 d’origine et le modèle quantifié, comparez les métriques (précision top-1 pour les classificateurs, F1 pour les détecteurs, perplexité pour les modèles de langage, BLEU pour la traduction, etc.), décidez en fonction des exigences de précision de l’application. L’entraînement conscient de la quantification (entraîner le modèle avec la quantification simulée dans la perte) récupère habituellement la majorité de la perte de précision.
Références
-
Documentation développeur Apple : Core ML. Référence du framework couvrant le comportement de dispatch automatique entre les unités de calcul. ↩
-
Documentation développeur Apple :
MLModelConfiguration.computeUnits. Cas d’énumération contrôlant quelles unités de calcul le modèle peut utiliser. ↩ -
Apple Developer : Apple silicon performance (introduction WWDC 2020 à l’architecture à mémoire unifiée d’Apple Silicon). ↩↩
-
Documentation développeur Apple : Core ML Model. Référence des formats
.mlpackageet.mlmodel. ↩ -
Documentation
coremltools. Le paquet Python open source d’Apple pour convertir des modèles entraînés depuis PyTorch, TensorFlow et ONNX vers Core ML. ↩↩ -
Documentation développeur Apple : Profiling Core ML models with Instruments. Le modèle Instruments Core ML pour l’analyse de latence et de dispatch couche par couche. ↩
-
Optimisation
coremltools. Techniques de quantification et patrons de préservation de la précision pris en charge par Core ML. ↩ -
Apple Developer : Core ML Models. La galerie Apple de modèles pré-entraînés prêts à être déposés dans des apps iOS. ↩
-
Documentation développeur Apple : Encrypting a Model in Your App. Le flux de chiffrement adossé à CloudKit pour les modèles Core ML. ↩
-
Documentation développeur Apple : Privacy manifest files. Le format pour déclarer les comportements de collecte de données et de suivi d’une app. ↩