Documentation

Faisabilité ANE : transformations équivalentes et un objectif 10× mesurable

Date de recherche : 2026-09-20. Matériel : M3 Max, GPU 40 cœurs, 128 GiB. Ce document décrit des hypothèses et des bornes mathématiques, pas l’affirmation d’une nouvelle accélération mesurée. Le point de départ est les poids Laya d’origine et le runtime MLX FP16 plus rapide. Les expériences et mesures d’ingénierie peuvent remplacer les observations de départ ci-dessous.

La meilleure première expérience est une réécriture à forme fixe et channel-first de tout le transformer, suivie d’une inspection du plan d’exécution. La cible d’ordre de grandeur la plus plausible est l’énergie par décision terminée, à condition que le modèle conserve une latence et une exactitude utiles. Changer seul un réglage d’unité de calcul Core ML n’est pas une preuve suffisante que le Neural Engine a exécuté le modèle.

Les expériences d’ingénierie ultérieures ont implémenté cette réécriture, et le rapport de vitesse/énergie mesuré enregistre désormais les résultats. Le candidat non compressé améliore l’efficacité mais n’a pas atteint la cible de 10×. Les hypothèses et le dénominateur d’origine ci-dessous sont conservés comme enregistrement de recherche ; utilise la comparaison compilée-MLX ultérieure pour les affirmations de performance mesurée.

Définir la cible avant d’optimiser

Pour les mêmes entrées, le même checkpoint, la même politique de précision et le même nombre de décisions terminées, définis :

t = elapsed time / completed decisions
P = average measured power over that same interval
E = integrated energy / completed decisions = P × t

S = t_MLX / t_candidate                    speed gain
R = P_MLX / P_candidate                    power reduction factor
S × R = E_MLX / E_candidate                 energy efficiency gain

Utilise la latence moyenne par bloc, pas un percentile de latence, dans cette identité. Rapporte P50 et P95 séparément. Un résultat 2× plus rapide à un cinquième de la puissance est une amélioration énergétique de 10×. Un résultat deux fois plus lent a besoin d’une réduction de puissance de 20× pour délivrer la même amélioration énergétique de 10×. Multiplier la vitesse par une amélioration énergétique déjà calculée compte le temps écoulé deux fois.

Il y a deux tests de puissance distincts :

  1. Inférence séquentielle saturée : mesure le débit réel, la latence et les joules par décision. Un candidat moins puissant mais plus lent n’est pas automatiquement plus efficace.
  2. Charge offerte égale, comme le même taux de tick Snake : les deux candidats doivent terminer le même travail dans l’échéance. Rapporte la puissance moyenne, l’énergie totale d’intervalle, les dépassements d’échéance et les décisions terminées. Dormir plus longtemps ou abandonner du travail n’est pas une optimisation.

Enregistre le domaine de puissance mesuré. La télémétrie CPU + GPU + ANE n’est pas nécessairement la puissance de toute la machine ni de la batterie, et ne doit pas être étiquetée comme telle. Rapporte l’énergie brute et, si utilisable, l’énergie appariée moins l’inactivité. Quand charge moins inactivité est proche du bruit, préserve l’incertitude au lieu de l’écrêter silencieusement et de rapporter un rapport énorme. Garde la tokenisation, les copies d’entrée, le repli CPU et le post-traitement à l’intérieur de la frontière comptable du point de mesure.

Preuves de départ et le dénominateur

Le benchmark MLX multilingue actuel mesure une seule question de 91 tokens à 7.870 ms P50 / 9.870 ms P95. Le benchmark MLX anglais mesure une question de 93 tokens à 13.334 / 13.734 ms. Ce sont des mesures predict de bout en bout, excluant le chargement du modèle et l’échauffement. Une nouvelle comparaison doit relancer le chemin MLX applicable le plus fort, y compris ses réglages opt-in de compilation et de cache de prompt là où la charge de travail le permet ; un résultat eager historique n’est pas un dénominateur permanent.

L’export Core ML multilingue existant mesure 11.277 ms P50 avec CPU + GPU, 78.037 ms avec ALL et 81.336 ms avec CPU + NE. Le dernier plan enregistre 1,318 opérations préférées pour le CPU et aucune opération préférée pour l’ANE ; 24 opérations SDPA ont des métadonnées d’appareil inconnues. Cela n’établit aucune affirmation d’exécution NE. Le plan liste de nombreuses opérations comme NE-supportées, ce qui diffère de NE-préférées. Apple décrit l’utilisation d’appareil du plan de calcul comme une utilisation d’appareil anticipée, donc même un plan favorable doit être corroboré par un profilage à l’exécution ou une activité NE observable.

Le portail de régression FP16 existant est un accord d’argmax de fixture de 100%, des sorties déterministes finies et une dérive absolue d’au plus 0.02 sur les probabilités calibrées et d’action. C’est un contrôle de fidélité de conversion sur un petit corpus. Il n’établit pas l’exactitude générale sur les tâches, la compétence Snake ou la qualité d’un modèle compressé.

Transformations de graphe équivalentes

L’étude de déploiement de Transformer d’Apple motive des activations BC1L en quatre dimensions, des convolutions 1×1, la division de l’attention en têtes et la réduction des copies de disposition. Son exemple publié de 10× est un modèle, un appareil et une baseline différents ; il ne peut pas être transféré à la comparaison MLX d’ici. Traite ces recommandations de disposition comme des candidats à tester sur ce système d’exploitation et cette puce, pas comme un contrat de prise en charge matérielle actuel complet.

Projections linéaires et le MLP à porte

Soit X[b,l,i] l’activation existante et définis U[b,i,0,l] = X[b,l,i]. Pour une couche linéaire,

Y[b,l,o] = sum_i W[o,i] X[b,l,i] + bias[o]
K[o,i,0,0] = W[o,i]
Conv2D(U,K)[b,o,0,l] = Y[b,l,o]

Cela change la disposition et la représentation des opérateurs sans changer la fonction à valeurs réelles. Conserve cette disposition sur tout l’encodeur et les deux couches de transformer de la tête de décision. Convertir vers elle et depuis elle autour de chaque couche linéaire peut effacer le bénéfice. QKV peut rester une seule convolution D → 3D ; divise sa sortie de canaux en Q, K et V. De même, préserve la projection d’encodeur fusionnée existante D → 2I, divise les canaux en valeur et porte, applique le GELU exact d’origine à la valeur, multiplie par la porte et projette I → D.

Pour FP16, une largeur de séquence divisible par 32 s’aligne aussi sur l’alignement de 64 octets du dernier axe décrit dans l’étude d’Apple. Les formes initiales sont B=1,L=96 pour la fixture d’API courte et B=3,L=64 pour le Snake compact. Une recommandation de multiple de 32 suit ici ce modèle de tampon ; ce n’est pas la permission de compléter chaque charge de travail à une grande longueur arbitraire. Snake n’a pas besoin de 96 tokens.

Attention et RoPE

Pour chaque tête, garde Q et V en (B,d,1,L) et transpose K en (B,L,1,d). Calcule :

score[b,k,0,q] = sum_c Q[b,c,0,q] K[b,k,0,c] / sqrt(d)
weight = softmax(score + additive_mask, axis=key)
out[b,c,0,q] = sum_k weight[b,k,0,q] V[b,c,0,k]

L’axe des clés est l’axe 1 dans cette représentation. Concatène les sorties de tête sur l’axe des canaux. C’est la même fonction d’attention ; un axe de softmax erroné la change silencieusement. L’implémentation d’attention de référence d’Apple démontre les deux contractions en quatre dimensions correspondantes. Inspecte les opérateurs MIL convertis : écrire un einsum ne garantit pas l’appareil ni l’abaissement visés.

Applique RoPE aux paires de canaux de chaque tête avant QK. Préserve la convention de moitiés séparées du checkpoint, les positions d’origine et le theta par couche. Dans ce checkpoint multilingue, RoPE complet et local utilisent tous deux theta 160000. Séparer les première et seconde moitiés de toutes les têtes concaténées ensemble est incorrect ; sépare à l’intérieur de chaque tête de 64 canaux. Une rotation dépendante de la position ne peut généralement pas être repliée dans une seule matrice de poids indépendante de la position.

La règle locale est bidirectionnelle abs(q-k) <= 64, borne incluse. Préserve le padding des clés et la règle existante des requêtes complétées. Les parties constantes dépendantes de la position peuvent être calculées avant le traçage pour des formes fixes ; changer le padding des échantillons doit toujours affecter le masque de clés. Remplacer une exclusion mathématique par un grand masque négatif fini est une approximation numérique, sauf si elle correspond au comportement en précision finie de l’implémentation d’origine ; vérifie les entrées adverses et complétées.

LayerNorm n’est pas interchangeable avec une autre normalisation

Pour chaque (b,l), réduis uniquement sur les canaux :

mu = mean_c U
v = mean_c (U-mu)^2
normalized = (U-mu) / sqrt(v + epsilon)
output = normalized * gamma + beta

Conserve l’epsilon d’origine, l’ordre affine, la variance de population, la normalisation identité de la première couche, le GELU exact et l’ordre des résidus. La LayerNorm de référence d’Apple utilise un ordre affine différent ; son adaptateur DistilBERT compense en transformant le biais. Copier directement cette classe et charger le state dict de Laya serait incorrect pour des biais non nuls. Une expression affine explicite dans l’ordre d’origine évite aussi de diviser par un gamma éventuellement nul.

Écrêter les activations, passer GELU à tanh ou remplacer LayerNorm par RMSNorm change la fonction. Si les valeurs au carré débordent, une remise à l’échelle positive est une option mathématiquement équivalente :

normalize(x/a, epsilon/a^2) = normalize(x, epsilon), for a > 0

L’accumulation en précision finie nécessite encore des tests de parité. Les réductions FP32 peuvent coûter des copies ou un repli CPU, donc inspecte le plan plutôt que de relâcher silencieusement le comportement numérique.

Déplacer le travail non pris en charge vers les frontières du modèle

Si la recherche d’embedding, le gather dynamique de marqueur ou la queue d’action empêche une région NE contiguë, fais un candidat distinct avec cette partition :

CPU: tokenizer → selected embedding rows → embedding LayerNorm
NE candidate: all encoder layers → type embedding addition → both heavy head layers
CPU: marker/CLS selection → small scorer → raw-probability features → action head

Seuls les points d’extrémité traversent les moteurs. Ne déporte pas l’attention ni la LayerNorm de chaque couche vers le CPU. En multilingue B=1,L=96, un tenseur d’embedding FP16 fait 147,456 octets ; en B=3,L=64, il fait 294,912 octets. Inclus ces copies et toute copie de sortie d’état caché complet dans la mesure de bout en bout.

La table de tokens multilingue a 196,608,000 paramètres mais chaque requête ne rassemble que ses lignes de tokens. Elle n’a pas besoin d’être embarquée dans un sous-graphe de transformer ANE, et elle ne doit pas être comptée comme une lecture complète de table à chaque prédiction. Sa LayerNorm n’a pas de dépendance à la position, donc une pré-normalisation hors ligne des lignes de table est équivalente en arithmétique réelle. Elle peut changer l’arrondi et la précision de stockage, ce qui nécessite son propre test de parité. La tête d’action consomme les probabilités issues des logits de marqueur bruts, avant la calibration de température ; reconstruire ses caractéristiques à partir des probabilités calibrées publiques change le comportement du checkpoint.

Limites arithmétiques sur une affirmation de latence 10×

Soit D la largeur cachée, I la largeur intermédiaire de l’encodeur à porte, N le nombre de couches d’encodeur et H=2 le nombre de couches de tête de décision. Le principal décompte de paramètres matriciels par token et l’arithmétique dense sont :

A = N(4D^2 + 3DI) + 12HD^2
F_dense(B,L) = 2BLA + 4B(N+H)L^2D

Les multiplications et les additions comptent séparément. Ces équations excluent les normes, les activations, les embeddings, le scoring, les masques, les copies et la surcharge du runtime. Ce n’est pas un profileur. Elles modélisent le calcul d’attention dense actuel même pour les couches locales masquées.

Checkpoint D / I / N A Octets de la matrice principale FP16 Travail dense à B=1,L=96 Calcul effectif requis pour 10× sous le P50 MLX actuel
Multilingue 768 / 1152 / 22 124,452,864 248.91 MB 24.574 GFLOP 31.23 TFLOP/s en 0.787 ms
Anglais / architecture typée 1024 / 2624 / 28 368,312,320 736.62 MB 71.848 GFLOP 53.89 TFLOP/s en 1.333 ms, en utilisant la baseline anglaise

Ce sont des débits atteints requis, pas des spécifications de pointe ANE affirmées. Une réécriture de disposition supprime la surcharge mais ne supprime pas ces projections denses. Le matériel doit aussi exécuter une chaîne séquentielle de 24 ou 30 blocs d’attention/MLP.

Un modèle de streaming optimiste donne un autre plancher conditionnel :

t >= max(F / effective_compute, bytes_from_DRAM / effective_bandwidth)

Le M3 Max à 40 cœurs GPU est spécifié avec 400 GB/s de bande passante mémoire unifiée. Si chaque matrice principale FP16 est récupérée depuis la DRAM une fois par requête, même un accès complet à cette bande passante coûte au moins 0.622 ms en multilingue et 1.842 ms en anglais. L’accès réel à la bande passante ANE peut être plus petit, et des poids mis en cache ou compressés changent l’hypothèse. Ce n’est pas une borne inférieure physique inconditionnelle. Cela montre pourquoi une latence anglaise de 10× est particulièrement exigeante en streaming non compressé, et pourquoi mesurer l’énergie est utile même quand la latence ne s’améliore que modestement.

Pour une fraction mesurée f du temps de bout en bout améliorée d’un facteur s, la loi d’Amdahl donne S = 1 / (1-f+f/s). Même une accélération infinie d’une région ne peut pas atteindre 10× à moins qu’elle n’occupe au moins 90% de la latence d’origine. La borne analogue utilise la fraction d’énergie mesurée, pas les FLOPs, lorsqu’on vise les joules par décision. L’optimisation de requêtes sélectionnées dans la tête finale ne supprime que quelques pour cent de l’arithmétique du modèle ; la parcimonie de l’attention locale est aussi négligeable à L<=64, où la fenêtre locale couvre toutes les positions. Ni l’une ni l’autre ne fournit une voie crédible vers 10× à elle seule.

Compression et changements architecturaux ont des contrats différents

Candidat Même fonction de checkpoint à valeurs réelles ? Ce qu’il peut changer de façon réaliste
Disposition BC1L, projections 1×1, positions/masques statiques, division en têtes Oui, quand les équations et les entrées sont préservées Ordonnancement, localité, partitionnement du compilateur, copies mémoire
Partition aux points d’extrémité CPU, normalisation d’embedding hors ligne, requêtes sélectionnées dans la tête finale Oui en arithmétique réelle ; valider l’arrondi Opérations non prises en charge, empreinte du paquet, un peu de travail inutilisé
Palettisation 8/6/4 bits ou quantification de poids Généralement non Trafic/stockage des poids et éventuellement énergie/latence d’inférence
Élagage de poids non nuls appris ou factorisation de rang faible Non, sauf s’il existe une structure algébriquement exacte Arithmétique matricielle et trafic après récupération/calibration
Sortie anticipée, élagage de tokens, moins de couches, étudiant plus étroit Non Économies potentiellement importantes ; nouveau modèle et contrat de qualité
Réutilisation d’états cachés sur des questions arbitraires Non pour cet encodeur bidirectionnel Raccourci invalide ; les états contextuels dépendent de la question
Mise en cache de réponses identiques pour toute l’entrée Exact pour les hits de cache Caractéristique de charge de travail ; pas la vitesse d’inférence non mise en cache

L’aperçu d’optimisation actuel d’Apple oriente vers la palettisation pour des gains de mémoire/latence NE et identifie le chemin de calcul W8A8 plus récent avec A17 Pro/M4. N’extrapole pas cette accélération matérielle plus récente à ce M3 Max. Le guide de performance de quantification avertit aussi que la déquantification des activations peut ralentir l’exécution CPU/GPU. Obtiens d’abord une baseline résidente sur l’ANE, puis teste la palettisation des poids de 8 bits vers le bas en préservant les normes/scorers sensibles selon le cas.

Compacter les poids FP16 sur huit ou quatre bits donne un rapport de stockage de poids idéal de 2× ou 4× avant métadonnées. Ce n’est pas un multiplicateur de latence égal : la décompression, le déplacement des activations et le calcul subsistent. L’élagage n’aide le runtime que si la représentation choisie exploite réellement les zéros. Retirer des têtes/couches arbitraires ou effectuer une troncature de rang faible nécessite une récupération de qualité et ne peut pas conserver l’identité du modèle d’origine sans réserve.

Pour une borne d’erreur de logits par entrée ||z'-z||_infinity <= delta, un certificat d’argmax suffisant est top1(z)-top2(z) > 2delta. Avec une température de calibration positive identique T, la borne de Lipschitz en norme infinie du softmax donne ||p'-p||_infinity <= delta/(2T). Ce sont des diagnostics utiles sur les entrées évaluées, pas un certificat global pour la quantification. Préserve des tranches d’évaluation distinctes pour les marges serrées et le multilingue ; les exemples saturés peuvent masquer de grandes erreurs de logits.

Trois expériences et portails d’acceptation

  1. Graphe NE équivalent à forme fixe. Exporte le multilingue B=1,L=96,K=4 et le Snake B=3,L=64,K=4 avec des projections BC1L, un RoPE correct par tête, une attention explicite et le LayerNorm/GELU d’origine. Compare les tableaux d’entrée et les sorties de couche individuelles par rapport au graphe d’origine. Inspecte quelles projections majeures et quels blocs d’attention sont préférés pour l’ANE, puis vérifie l’activité NE réelle à l’exécution. Un simple décompte d’opérations prises en charge n’est pas un succès. Relance la baseline MLX optimisée correspondante en blocs alternés.
  2. Un seul îlot de transformer contigu. Si le premier graphe se fragmente, déplace l’embedding et la petite queue finale vers les frontières CPU. Compare-le au candidat graphe complet sous la même mesure de puissance. Ne garde un candidat que si les prédictions complètes améliorent la latence ou l’énergie au-delà de la variation observée d’une exécution à l’autre. Inclus toutes les copies ; un encodeur isolé rapide ne suffit pas.
  3. Compression centrée sur l’énergie après que le placement fonctionne. Crible la palettisation 8 bits, puis 6/4 bits comme variantes approximatives distinctes. Exécute le portail de fixture inchangé, des tâches choice/score/noul retenues, des entrées multilingues, des quasi-égalités et des trajectoires Snake. Publie l’exactitude, la dérive de probabilité et la calibration aux côtés de la performance. Une compression agressive ou une distillation appartient à un modèle nommé séparément si elle change le comportement appris.

Avant une affirmation de lancement, utilise les mêmes hashs de checkpoint/entrée et un ordre alterné baseline/candidat ; exclue la compilation à froid mais rapporte-la séparément. Utilise au moins cinq blocs soutenus par finaliste et conserve les échantillons bruts de latence, d’appels terminés et de puissance. Exige l’accord de la fixture d’origine et les tolérances de probabilité existantes sans les desserrer pour faire passer le candidat, plus des sorties finies stables et une mémoire bornée. Mesure les entrées longues et aux frontières de forme séparément des démos courtes à forme fixe.

Ne déclare 10× que lorsque le rapport pertinent de vitesse, de puissance à charge égale ou d’énergie est d’au moins dix avec une incertitude qui soutient l’affirmation, tout en respectant les limites de latence et de qualité de tâche énoncées. Si la borne inférieure d’incertitude n’atteint pas dix, rapporte le rapport mesuré. Un gain d’énergie plus petit avec une exécution NE vérifiée reste une preuve utile ; ce n’est pas un résultat d’ordre de grandeur.

Provenance de la documentation

A utilisé le workflow Context7 CLI requis : résolu Core ML Tools vers /apple/coremltools, puis interrogé l’abaissement d’opérateurs/dispositions de transformer et le comportement de compression NE (trois commandes au total). A vérifié l’article de recherche d’Apple, la source de référence, la documentation actuelle d’optimisation Core ML, la documentation du plan de calcul et la spécification d’appareil liée ci-dessus. Les équations du modèle, les décomptes de paramètres et les mesures de départ ont été dérivés de ce dépôt et de son frère MLX. Aucun benchmark GPU/ANE concurrent n’a été exécuté par cette branche de recherche.