4 points par GN⁺ 2026-03-03 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Analyse directe de l’architecture interne de l’Apple Neural Engine (ANE) et mise en œuvre d’une méthode pour contourner CoreML et accéder directement au matériel
  • Suppression de la couche d’abstraction de CoreML et exécution directe de la compilation, du chargement et de l’exécution des modèles via l’API _ANEClient
  • Analyse de MIL (Machine Learning Intermediate Language) et du format binaire E5, confirmant que l’ANE est un moteur d’exécution de graphes fondé sur des primitives d’opération fixes
  • Démonstration de la possibilité d’un transfert de données zero-copy entre GPU et ANE grâce à la mémoire partagée IOSurface
  • Cette recherche constitue le premier volet d’une trilogie consacrée à l’évaluation des performances réelles du M4 ANE et à ses possibilités d’apprentissage, avec pour enjeu le premier cas de contrôle direct d’un matériel privé d’Apple

Approche de rétro-ingénierie par collaboration humain–IA

  • La recherche a été menée en collaboration entre un chercheur humain et Claude Opus 4.6 d’Anthropic
    • L’humain a défini les axes d’exploration, et l’IA a assuré l’analyse des données et l’écriture du code
  • Le point de départ était la question suivante : « Peut-on entraîner directement des modèles sur l’Apple Neural Engine ? »
  • Apple ne publie ni l’ISA, ni l’architecture interne, ni l’interface de programmation directe de l’ANE
    • L’accès n’est possible qu’à travers CoreML, ce qui rend difficile la compréhension du fonctionnement matériel
  • L’équipe a donc remonté l’ensemble de la pile logicielle, de CoreML jusqu’au pilote noyau IOKit, afin d’obtenir un chemin de code permettant de contrôler directement l’ANE

Architecture du Neural Engine

  • L’ANE n’est pas un GPU ni un CPU, mais un graph execution engine
    • Il exécute l’intégralité d’un graphe de réseau neuronal compilé comme une opération atomique unique
  • L’ANE de la puce M4 (nom de code H16G) dispose de 16 cœurs, d’une profondeur de file de 127 requêtes, d’un contrôle DVFS indépendant et d’une coupure d’alimentation à 0 mW au repos
  • Apple a introduit pour la première fois un ANE à 2 cœurs avec l’A11 (2017), puis l’a étendu à chaque génération

Ce qui distingue cette étude des travaux précédents

  • Ressources publiques existantes :
    • la documentation sur le fonctionnement de l’ANE et l’analyse de performances de Matthijs Hollemans
    • les premiers exemples de rétro-ingénierie de mdaiter/ane
    • le pilote Linux rétro-ingéniéré de Asahi Linux
    • le code officiel d’optimisation des transformers apple/ml-ane-transformers
  • Apports originaux de cette étude :
    • accès direct réussi à l’API _ANEClient sans CoreML
    • déchiffrement du chemin de compilation MIL en mémoire
    • mesure du débit réel après suppression de la surcharge de CoreML
    • exécution d’apprentissage de modèle sur un matériel conçu pour l’inférence uniquement

Méthodologie d’analyse

  • Exploration de classes : extraction de la liste des classes internes à AppleNeuralEngine.framework via la commande dyld_info -objc
  • Method swizzling : interception des appels CoreML pour identifier le chemin d’appel vers les frameworks privés
  • Analyse binaire : décodage des bundles E5 compilés pour comprendre le format des programmes
  • Analyse de scaling : variation de la taille des matrices, de la profondeur des graphes et du nombre de canaux pour déduire la topologie matérielle
  • Au final, découverte de plus de 40 classes privées, dont _ANEClient, _ANEModel, _ANERequest, _ANEIOSurfaceObject, _ANEInMemoryModel

Contourner CoreML : accès direct à _ANEClient

  • _ANEClient permet de contrôler directement tout le pipeline compilation → chargement → évaluation d’un modèle
  • CoreML n’est en pratique qu’une couche de confort qui encapsule ce processus
  • L’ANE prend en charge jusqu’à 127 requêtes d’évaluation simultanées (queue depth), ce qui l’optimise pour l’inférence en streaming à haut débit
  • Les buffers d’E/S basés sur IOSurface permettent un transfert par mémoire partagée entre GPU et ANE

MIL : le langage d’entrée de l’ANE

  • CoreML utilise MIL (Machine Learning Intermediate Language) plutôt que ONNX ou protobuf
    • Il repose sur le modèle SSA (static single assignment), avec types et formes explicitement définis
    • Dans l’exemple de code, l’opération matmul est exprimée de manière explicite
  • Le layout des tenseurs suit le format NCDHW + Interleave, avec une structure [Batch, Channels, Depth, Height, Width]

Format binaire E5

  • Les programmes MIL sont compilés en binaires E5 FlatBuffer
    • multiplication de matrices 1024×1024 : 2 688 octets, multiplication 128×128 : 2 680 octets
    • la taille du code étant presque identique, cela indique qu’il ne contient pas l’algorithme de calcul matriciel lui-même, mais seulement des informations de configuration paramétrées
  • Cela signifie que l’ANE exécute les graphes en combinant des primitives d’opération fixes (Conv, MatMul, Elementwise, etc.)

Chemin de compilation en mémoire

  • _ANEInMemoryModelDescriptor permet de compiler du MIL en mémoire sans accès disque
  • Principaux problèmes et solutions :
    • milText requiert non pas un NSString, mais un NSData (octets UTF-8)
    • weights doit être fourni sous forme de dictionnaire nom–données
    • un accès à un répertoire temporaire est requis en interne → les droits d’écriture sont indispensables
  • Une faute de frappe, Desctiptor, a été repérée dans le code interne d’Apple

Profil matériel

  • D’après l’analyse IOKit, l’ANE dispose de canaux indépendants de gestion de l’alimentation et de l’horloge (DVFS)
    • présence de divers déclencheurs matériels/logiciels comme ANE_ADCLK_TRIG et ANE_PPT_TRIG
  • Parmi les opérations prises en charge repérées dans ANECompiler.framework, Conv apparaît comme la primitive centrale
    • la partie 2 doit montrer qu’en convertissant un 1×1 Conv en MatMul, il est possible d’obtenir un gain de performances de 3×

Protocole IOSurface

  • Toutes les entrées/sorties de données passent par des objets de mémoire partagée IOSurface
    • le mécanisme est identique à celui du partage de textures GPU
    • cela ouvre la possibilité de construire un pipeline zero-copy GPU↔ANE

Structure du cache de compilation

  • Le compilateur ANE met en cache les binaires E5 sur disque
    • chemin : ~/Library/Caches/.../com.apple.e5rt.e5bundlecache/.../H16G.bundle/
    • première compilation : 20–40 ms, exécution immédiate en cas de cache hit
    • c’est favorable à l’inférence, mais l’apprentissage nécessite une recompilation quand les poids changent

Zones encore inexplorées

  • Classes pas encore analysées :
    • _ANEChainingRequest — possibilité d’enchaîner plusieurs modèles dans un seul dispatch
    • _ANESharedEvents, _ANESharedSignalEvent, _ANESharedWaitEvent — fence/signal pour la synchronisation GPU↔ANE
    • _ANEPerformanceStats — possibilité de compteurs de performances matériels
    • _ANEVirtualClient — possible approche de virtualisation multiprocessus
  • Éléments encore inconnus :
    • la microarchitecture des cœurs ANE et l’ISA
    • la méthode d’affectation des opérations aux cœurs dans le graphe
    • la fréquence d’horloge et la structure SRAM

Prochaines étapes

  • Partie 2 : scaling de la multiplication de matrices, goulots d’étranglement SRAM, comparaison des performances de Conv et MatMul, validation du chiffre « 38 TOPS » annoncé par Apple
  • Partie 3 : entraînement de réseaux neuronaux sur l’ANE
  • Tout le code est publié dans le répertoire ane/ de github.com/maderix/ANE
  • Environnement de test : M4 Mac Mini, macOS 15.x

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.