- Analiza directamente la arquitectura interna del Apple Neural Engine (ANE) e implementa una forma de sortear CoreML y acceder directamente al hardware
- Elimina la capa de abstracción de CoreML y, mediante la API
_ANEClient, compila, carga y ejecuta modelos de forma directa
- Al analizar MIL (Machine Learning Intermediate Language) y el formato binario E5, confirma que el ANE es un motor de ejecución de grafos basado en primitivas de operación fijas
- Demuestra la posibilidad de transferencia de datos zero-copy entre GPU↔ANE usando memoria compartida IOSurface
- Esta investigación es la primera de una serie de tres partes que explora la medición del rendimiento real y la posibilidad de entrenamiento en el ANE del M4, y destaca por ser el primer caso de control directo sobre hardware privado de Apple
Enfoque de ingeniería inversa mediante colaboración humano–IA
- La investigación se realizó en colaboración entre un investigador humano y Claude Opus 4.6 de Anthropic
- El humano definió la dirección de exploración y la IA se encargó del análisis de datos y la escritura de código
- El objetivo partió de la pregunta: “¿Se puede entrenar directamente un modelo sobre el Apple Neural Engine?”
- Apple no publica la ISA, la arquitectura interna ni la interfaz de programación directa del ANE
- Solo es accesible mediante CoreML, lo que dificulta comprender cómo funciona el hardware
- Por ello, se rastreó en reversa toda la pila de software desde CoreML hasta el driver de kernel IOKit, asegurando una ruta de código para controlar el ANE directamente
Arquitectura del Neural Engine
- El ANE no es una GPU ni una CPU, sino un motor de ejecución de grafos (graph execution engine)
- Ejecuta un grafo de red neuronal compilado completo como una sola operación atómica
- El ANE del chip M4 (nombre clave H16G) tiene 16 núcleos, profundidad de cola de 127 solicitudes, control DVFS independiente y apagado de energía a 0 mW en reposo
- Apple introdujo por primera vez un ANE de 2 núcleos en el A11 (2017) y lo ha ido ampliando en cada generación
Diferencias frente a investigaciones previas
- Material público existente:
- Documentación del funcionamiento del ANE y análisis de rendimiento de Matthijs Hollemans
- Muestras iniciales de ingeniería inversa de mdaiter/ane
- Driver de Linux con ingeniería inversa de Asahi Linux
- Código oficial de optimización para transformers de apple/ml-ane-transformers
- Aportes originales de esta investigación:
- Acceso directo exitoso a la API
_ANEClient sin CoreML
- Descifrado de la ruta de compilación MIL en memoria
- Medición del throughput real tras eliminar la sobrecarga de CoreML
- Ejecución de entrenamiento de modelos en hardware pensado solo para inferencia
Metodología de análisis
- Exploración de clases: extracción de la lista de clases dentro de
AppleNeuralEngine.framework con el comando dyld_info -objc
- Method swizzling: interceptar llamadas de CoreML para identificar la ruta de invocación de frameworks privados
- Análisis binario: descifrado de bundles E5 compilados para entender el formato del programa
- Análisis de escalamiento: inferencia de la topología del hardware variando tamaño de matrices, profundidad del grafo y número de canales
- Como resultado, se encontraron más de 40 clases privadas, entre ellas
_ANEClient, _ANEModel, _ANERequest, _ANEIOSurfaceObject, _ANEInMemoryModel
Sortear CoreML: acceso directo a _ANEClient
- Con
_ANEClient es posible controlar directamente toda la tubería de compilación → carga → evaluación del modelo
- CoreML no es más que una capa de conveniencia que envuelve ese proceso
- El ANE admite hasta 127 solicitudes de evaluación simultáneas (queue depth), optimizado para inferencia de streaming de alto throughput
- El uso de buffers de E/S basados en IOSurface permite transferencia de memoria compartida entre GPU y ANE
MIL: el lenguaje de entrada del ANE
- En lugar de ONNX o protobuf, CoreML usa MIL (Machine Learning Intermediate Language)
- Basado en asignación estática única (SSA), con tipos y formas explícitos
- En el código de ejemplo, la operación
matmul se expresa claramente
- El layout de tensores sigue el formato NCDHW + Interleave, con estructura
[Batch, Channels, Depth, Height, Width]
Formato binario E5
- Los programas MIL se compilan a binarios E5 FlatBuffer
- Multiplicación de matrices 1024×1024: 2,688 bytes; multiplicación de matrices 128×128: 2,680 bytes
- El tamaño del código es casi idéntico → solo contiene información de configuración parametrizada, no un algoritmo específico para la operación matricial
- Esto indica que el ANE ejecuta grafos combinando primitivas de operación fijas (Conv, MatMul, Elementwise, etc.)
Ruta de compilación en memoria
- Con
_ANEInMemoryModelDescriptor es posible compilar MIL en memoria sin acceso a disco
- Principales problemas y soluciones:
milText no requiere NSString, sino NSData (bytes UTF-8)
weights debe tener formato de diccionario de mapeo nombre–datos
- Internamente se necesita acceso a un directorio temporal → es indispensable contar con permisos de escritura
- En el código interno de Apple se encontró el error tipográfico
Desctiptor
Perfil de hardware
- Según el análisis de IOKit, el ANE tiene canales independientes de gestión de energía y reloj (DVFS)
- Existen varios disparadores de hardware/software como
ANE_ADCLK_TRIG y ANE_PPT_TRIG
- Entre las operaciones compatibles observadas en ANECompiler.framework, Conv aparece como la primitiva principal
- En la Parte 2 se mostrará que convertir Conv 1×1 en MatMul permite mejorar el rendimiento 3 veces
Protocolo IOSurface
- Toda la entrada y salida de datos se realiza mediante objetos de memoria compartida IOSurface
- Es el mismo mecanismo usado para compartir texturas en GPU
- Existe la posibilidad de construir una tubería zero-copy GPU↔ANE
Estructura de la caché de compilación
- El compilador del ANE almacena en caché los binarios E5 en disco
- Ruta:
~/Library/Caches/.../com.apple.e5rt.e5bundlecache/.../H16G.bundle/
- La primera compilación tarda entre 20 y 40 ms; con cache hit, la ejecución es inmediata
- Esto favorece la inferencia, pero en entrenamiento es necesario recompilar cuando cambian los pesos
Áreas aún no exploradas
- Clases todavía no analizadas:
_ANEChainingRequest — posible encadenamiento de varios modelos en un solo dispatch
_ANESharedEvents, _ANESharedSignalEvent, _ANESharedWaitEvent — fences/señales para sincronización GPU↔ANE
_ANEPerformanceStats — posible acceso a contadores de rendimiento del hardware
_ANEVirtualClient — posible enfoque de virtualización multiproceso
- Elementos aún no confirmados:
- La microarquitectura e ISA de los núcleos del ANE
- Cómo se asignan los núcleos a las operaciones dentro del grafo
- La frecuencia de reloj y la estructura de SRAM
Próximos pasos
- Parte 2: escalamiento de multiplicación de matrices, cuellos de botella de SRAM, comparación de rendimiento entre Conv y MatMul, y verificación de la cifra de “38 TOPS” de Apple
- Parte 3: entrenamiento de redes neuronales en el ANE
- Todo el código está publicado en el directorio
ane/ de github.com/maderix/ANE
- Entorno de pruebas: M4 Mac Mini, macOS 15.x
2 comentarios
Referencia: controlador ANE fuera del árbol de Asahi Linux
Comentarios en Hacker News
Creo que el autor hizo un trabajo realmente excelente, y también espero la parte 3
Yo uso principalmente bibliotecas de ML en Python como lightgbm, sklearn, xgboost y numpy
Me pregunto si estas operaciones se aceleran en hardware de Apple, y si hay alguna forma sencilla de medirlo con benchmarks
La mayoría de los benchmarks están al nivel de funciones en C, así que no sé si el efecto existe en bibliotecas de alto nivel
Me dio risa que ChatGPT me dijera que comparara Intel Mac con Apple Silicon. Supongo que por esto la gente todavía odia a la IA
La razón es que las NPU están muy especializadas según cada fabricante, así que para los desarrolladores open source es difícil darles soporte
El Apple ANE no es la excepción, y esta investigación parece un intento de resolver ese problema específicamente para el Apple ANE
Según el artículo Inside the M4 Apple Neural Engine, alcanza 6.6 FLOPS/W y cuando no se usa se apaga por completo, consumiendo 0W
Apple calculó “38 TOPS INT8” como FP16 19 TFLOPS × 2, pero el hardware real no ejecuta operaciones INT8 al doble de velocidad
Seguir esta forma de cálculo se siente, de manera poco habitual en Apple, como una expresión exagerada
Los LLM pueden producir información falsa pero convincente al punto de engañar incluso a expertos
Me cuesta creer que hayan verificado manualmente todos los hechos. En ese sentido, casi agradezco que lo advirtieran de antemano, porque así ni siquiera necesito leerlo
En el artículo también se notan algunos benchmarks raros de ese tipo
Incluso antes de los LLM, en la academia ya había muchos papers manipulados y estudios imposibles de reproducir
Al final, este tipo de análisis solo se puede considerar confiable cuando más ingenieros lo validan
Hay muchas historias que no tienen relación con el tema
Tal vez esa sea una de las razones por las que Awni, líder del proyecto MLX, dejó Apple
Pero me gusta que este artículo confirme y amplíe ese contenido con más profundidad
Si CoreML realmente casi no tiene sobrecarga en operaciones grandes de matmul, entonces hay bastante margen para usar el ANE en frameworks de IA local para la etapa de prefill
Aun así, la etapa de decode está limitada por el ancho de banda de memoria, y el proceso de convertir matmul en convolución 1x1 es ineficiente, así que no es una ventaja clara
Se llama Core AI, y supuestamente permitirá integrar LLM de terceros en apps con mayor facilidad
Artículo relacionado: boletín de Bloomberg
Aun así, me pareció muy útil e interesante
También vale la pena revisar el repositorio de Github mencionado en el artículo
Esa parte sí deja claro que fue escrita por IA
Más importante que la ingeniería inversa del ANE es cuánto ha logrado Manjeet ampliar sus capacidades de ingeniería con ayuda de la IA
Este es justamente el momento en que la IA está acelerando la productividad de los desarrolladores