Documentación

Mediciones de velocidad y energía del Neural Engine

La reescritura ANE FP16 mejora la velocidad de predicción completa en 1.39× y la energía estimada de todo el sistema por decisión en 2.78× frente a MLX FP16 compilado. El candidato W8 K-means validado por separado alcanza 1.42× y 3.19× respectivamente. Ninguno cumple el objetivo solicitado de 10×. Son resultados locales en un M3 Max, con los límites de precisión y medición de potencia que se indican abajo.

La implementación y los experimentos de conversión están en ANE_ENGINEERING.md; las cotas matemáticas y los contratos de fidelidad están en ANE_MATH.md.

Comparación final sostenida de decisiones cortas

M3 Max, 40 núcleos de GPU, 128 GiB, macOS 27.2. El mismo checkpoint de origen multilingüe, las mismas ocho variantes de estado de factura, una pregunta de cuatro opciones por solicitud, 91 tokens reales rellenados a 96. Sin caché de salida ni tokens generados. Los tres modelos permanecen residentes; la carga, compilación y calentamiento quedan fuera de los intervalos medidos.

La línea base habilita mx.compile, la caché de prefijo de prompt y los buckets de forma de 32 tokens. Es más rápida que la línea base MLX eager histórica. El candidato ANE FP16 conserva los pesos originales, con un cuerpo transformer completo de Core ML, búsqueda de embeddings en el host y una cola de acción en FP32 sobre la CPU. W8 usa compresión de paleta solo de pesos por K-means agrupado, no aritmética W8A8; sus activaciones siguen en FP16 y su cola de acción en el host sigue en FP32.

Métrica MLX GPU FP16, compilado ANE FP16 ANE W8 K-means
Decisiones completadas 17,184 23,961 24,453
Duración activa medida 120.02 s 120.02 s 120.02 s
P50 de extremo a extremo 6.937 ms 4.976 ms 4.879 ms
P95 de extremo a extremo 7.393 ms 5.307 ms 5.227 ms
Tiempo medio transcurrido por decisión 6.984 ms 5.009 ms 4.908 ms
Estimación de potencia media de todo el sistema 61.39 W 30.75 W 27.39 W
Energía de todo el sistema por decisión 0.4288 J 0.1540 J 0.1344 J
Energía por decisión con reposo restado 0.3393 J 0.0888 J 0.0715 J
Ganancia de velocidad frente a MLX compilado 1× 1.394× 1.423×
Ganancia de energía de todo el sistema frente a MLX compilado 1× 2.784× 3.189×
Ganancia de energía con reposo restado frente a MLX compilado 1× 3.823× 4.749×

Las relaciones usan medias del intervalo, incluyendo todo el trabajo completado:

FP16: speed 1.394 × average system-power ratio 1.997 = energy gain 2.784
W8:   speed 1.423 × average system-power ratio 2.241 = energy gain 3.189

Multiplicar otra vez una relación de energía por la velocidad cuenta el tiempo transcurrido dos veces. La fila con reposo restado usa un límite de medición distinto; no significa que la potencia de todo el portátil baje 3.8–4.7×. Son intervalos de rendimiento saturado. Haría falta un experimento con la misma tasa de solicitudes para una afirmación de potencia a FPS fijos. W8 mejora la velocidad media solo alrededor de un 2.1% respecto a FP16 en esta sesión, mientras que su paquete del cuerpo se reduce de 251.91 a 129.29 MB decimales. El tamaño del paquete excluye el checkpoint original/tabla de embeddings del host y no es la memoria total del runtime.

Cada implementación ejecutó seis bloques de 20 segundos en tres ciclos equilibrados de MLX, ANE FP16, ANE W8, ANE W8, ANE FP16, MLX. Diez segundos de muestreo en reposo separan los bloques; los tres primeros segundos de reposo se descartan y se promedia la potencia en reposo asentada adyacente. Los rangos de potencia por bloque de los backends fueron 60.32–62.38 W para MLX, 29.28–35.14 W para ANE FP16 y 26.68–27.95 W para ANE W8. Había otras aplicaciones de escritorio abiertas; la alternancia y el muestreo en reposo adyacente reducen, pero no eliminan, la incertidumbre de carga de fondo y de sensor.

Las 65,598 predicciones coinciden con la salida redondeada del calentamiento de su backend para el estado correspondiente. Los tres backends seleccionan la misma respuesta en estos ocho estados. La suite de fidelidad aparte es más amplia: FP16 L96 supera 59/59 preguntas que caben con una deriva máxima de probabilidad de 0.002925; W8 supera esas mismas 59 con deriva 0.014393 bajo el umbral sin cambios de 0.02. El resultado completo de 63/63 pertenece al modelo FP16 L1024 exportado por separado. Son fixtures de regresión, no una afirmación de precisión general en tareas ni de calibración preservada en entradas arbitrarias.

La ejecución conservó 1,101 muestras de potencia; el hueco máximo fue de 0.510 segundos y la potencia de sistema máxima registrada fue de 74.47 W. No se descartó ninguna muestra. El RSS por bloque se registra para el proceso compartido con todos los modelos y buffers de grabación residentes; esos valores no pueden asignarse a la memoria del modelo de un backend individual. Las huellas (fingerprints) actuales del runtime y del paquete se guardan con el informe.

Llamadas sin procesar finales y muestras PSTR · Resumen auditado e intervalos bootstrap dentro de la sesión

El piloto anterior solo de FP16 midió 1.410× de velocidad y 2.939× de ganancia bruta de energía del sistema. Es anterior a las últimas comprobaciones de entrada y a la instrumentación de estabilidad por llamada; la nueva ejecución de tres brazos de arriba es la comparación publicada para el runtime final. Una advertencia de metadatos en el informe sin procesar final describía inicialmente el suelo histórico de suma de componentes de macmon de forma incondicional; una entrada aditiva metadata_corrections aclara que esta ejecución usó solo PSTR. Los campos originales y todas las mediciones se conservan.

La compatibilidad con Snake es una carga de trabajo aparte

El mismo planificador de Snake publicado, los prompts compactos y la política de seguridad se ejecutaron tanto en el adaptador ANE FP16 como en MLX compilado, alternando el orden de evaluación sobre estados en vivo idénticos. Las semillas 101 y 102 completaron 300 pasos cada una: 600/600 acciones propuestas y ejecutadas coinciden, cero muertes y cero intervenciones del escudo. Las puntuaciones finales fueron 9 y 10, con longitudes de serpiente 15 y 16. La diferencia máxima de probabilidad de movimiento fue de 0.0036. Esto valida esta comparación de trayectorias FP16, no el comportamiento de Snake de un modelo comprimido ni la supervivencia ilimitada.

Semilla Decisión completa ANE P50 / P95 Decisión completa de MLX compilado P50 / P95
101 23.45 / 27.10 ms 17.14 / 23.58 ms
102 17.68 / 27.30 ms 19.18 / 33.27 ms

El adaptador ANE ejecuta tres preguntas secuencialmente en B1/L96; MLX procesa las tres preguntas por lotes hasta L64. Estos tiempos incluyen características del planificador y predicciones completas, excluyen el trabajo del otro backend, el paso de juego y el renderizado de terminal, y muestran una variación considerable. No demuestran una aceleración constante de Snake ni un ritmo de renderizado máximo estable. El resultado de 4.98 ms por pregunta no debe anunciarse como el tiempo de fotograma completo de Snake. Una exportación ANE B3/L64 dedicada sería una tarea aparte de optimización y validación.

Estados, salidas y tiempos sin procesar de Snake

python -m benchmarks.snake artifacts/ane-repro/body96/model.mlpackage \
  /path/to/original/laya-multilingual --ane --mlx-compiled \
  --steps 300 --seeds 101 102 --output artifacts/ane-snake.json

Límite de medición y limitaciones de telemetría

Cada llamada cronometrada incluye la construcción del prompt, la tokenización, la construcción de arrays, la búsqueda de embeddings en el host cuando corresponde, la ejecución síncrona del modelo, las características de acción, la calibración y el formateo de salida. MLX evalúa sus salidas perezosas; Core ML devuelve arrays NumPy ya completados. Esto compara predicciones sin caché, no kernels aislados del modelo.

La comparación final usa el pequeño muestreador solo PSTR sin privilegios. Fija la API SMC de bajo nivel de macmon 0.8.2, abre una conexión de solo lectura y muestrea el valor original de PSTR cada 500 ms. No lee los contadores de componentes de IOReport. Es una estimación por sensor de todo el sistema, no una medición externa de potencia de pared ni de batería. El hash del ejecutable y la procedencia del código fuente se registran con los resultados sin procesar.

Este muestreador aparte fue necesario porque el CLI oficial de macmon calcula sys_power = max(PSTR, component_sum), como se ve en su código fuente. Los contadores de CPU y ANE normalmente devolvían cero en este sistema operativo, y luego una muestra saltó a aproximadamente 38,021 W de CPU y 2,068 W de ANE. El suelo de componentes propagó ese fallo a una lectura de sistema de 40,089 W. La causa precisa de la anomalía de IOReport no está resuelta; el valor original de PSTR no puede recuperarse de esa muestra. Se rechazó toda la ejecución de energía afectada, sin eliminar ni recortar la muestra mala. Su registro sin procesar sigue disponible, pero sus agregados de energía almacenados no deben usarse como resultados.

La ejecución anterior solo de FP16 usó la versión oficial de macmon v0.8.2, cuyo SHA256 del archivo se verificó como 588d5bde79885ba36f693e5150911c10c3ad208a2e418a3f2aa827ac84a2d973. Superó las comprobaciones de cordura posteriores y sigue siendo evidencia histórica. La ejecución final solo PSTR vuelve a medir todos los backends con un único muestreador consistente.

El arnés integra vatios sobre marcas de tiempo de recepción monótonas con límites interpolados. Las lecturas de sistema faltantes, no positivas, no finitas o superiores a 500 W rechazan la ejecución. El techo de 500 W es una comprobación de cordura deliberadamente holgada para este M3 Max, no una cota de precisión calibrada. Los huecos superiores a max(2 seconds, 3 × sample interval) también rechazan la ejecución. El resumen verifica ciclos equilibrados completos, estabilidad por llamada, recuentos de llamadas, energía activa, ambos intervalos de reposo adyacentes y la energía resultante con reposo restado, contra las muestras sin procesar. La energía incremental conserva su signo; nunca se recorta para fabricar una relación grande.

El muestreador directo omite los campos de potencia de CPU/GPU/ANE porque no los mide. Los contadores de componentes históricos faltantes o en cero no pueden establecer energía cero ni la ausencia de ejecución en ANE. El bootstrap remuestrea ciclos equilibrados completos; tres ciclos de una sola sesión de escritorio no caracterizan toda la carga de fondo, ejecuciones futuras ni la precisión del sensor. Ninguna de las relaciones medidas se acerca a 10×.

¿El Neural Engine ejecuta trabajo realmente?

El plan de cómputo de Core ML del grafo B1/L96 reescrito coloca las 6,390 operaciones no constantes en MLNeuralEngineComputeDevice; las 3,809 entradas desconocidas restantes son constantes. Es una colocación prevista, no evidencia de hardware suficiente por sí misma. La exportación ordinaria con SDPA no tenía operaciones preferidas por NE en este sistema.

Una traza aparte de Instruments Core ML de 15.97 segundos, tomada mientras el candidato se ejecutaba con CPU_AND_NE, capturó 3,124 intervalos activos de “Neural Engine Prediction” y una carga no relacionada de un modelo de sistema en caché. La tabla de hardware exportada proporciona, por tanto, evidencia positiva de actividad de ANE en runtime además del plan de cómputo. La tabla es global y no asocia un PID ni una identidad de modelo a cada predicción; la tabla de model-signpost de Core ML estaba vacía en esta grabación. No atribuimos todos los intervalos de hardware exclusivamente a Laya ni afirmamos que el trabajo del host se ejecute en ANE.

Los eventos de hardware en la lista de permitidos incluyen solo marcas de tiempo, duración, dispositivo, etiqueta y estado. Los archivos completos de Instruments y los metadatos del entorno del proceso permanecen en el directorio ignorado artifacts/. El trazado fue independiente de la prueba de energía, y los intervalos de hardware instrumentados no se usan como resultado de latencia de extremo a extremo.

Reproducir

Primero crea y valida los paquetes fijos L96 FP16 y W8 K-means con los comandos del informe de ingeniería. Esos comandos escriben en directorios nuevos bajo artifacts/ane-repro/. Compila el muestreador de sensor directo en local; no se instala ningún daemon del sistema ni servicio con privilegios.

pip install -e '.[convert,dev,compare,research]'
cargo build --release --locked --manifest-path benchmarks/pstr_sampler/Cargo.toml
python -m benchmarks.energy \
  --source /path/to/original/laya-multilingual \
  --candidate artifacts/ane-repro/body96-w8km/model.mlpackage \
  --fp16-candidate artifacts/ane-repro/body96/model.mlpackage \
  --candidate-factory experiments.ane_engineering.runtime:ANEAgent \
  --sampler benchmarks/pstr_sampler/target/release/pstr-sampler --pstr-only \
  --cycles 3 --seconds 20 --idle-seconds 10 \
  --output artifacts/energy.json

python -m benchmarks.energy_summary artifacts/energy.json \
  --output artifacts/energy-summary.json

Para diagnósticos de runtime independientes, inicia benchmarks.trace_ane, espera a su archivo PID de listo y luego adjunta Instruments sin que se ejecute otra carga de trabajo de modelo:

python -m benchmarks.trace_ane \
  --source /path/to/original/laya-multilingual \
  --package artifacts/ane-repro/body96/model.mlpackage \
  --seconds 90 --ready artifacts/trace.pid
# From another terminal; use the PID written to that file.
xcrun xctrace record --template 'Core ML' --attach <PID> \
  --time-limit 15s --output artifacts/ane.trace
xcrun xctrace export --input artifacts/ane.trace --toc \
  --output artifacts/toc.xml
xcrun xctrace export --input artifacts/ane.trace \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="ane-hw-intervals"]' \
  --output artifacts/hardware.xml
python -m benchmarks.trace_summary --hardware-xml artifacts/hardware.xml \
  --toc-xml artifacts/toc.xml --output artifacts/hardware-summary.json

El checkpoint original y la exportación más corta tienen límites de contexto distintos. El runtime L96 rechaza las entradas que no caben; un resultado de velocidad con carga de trabajo corta no demuestra el rendimiento a 512/1024 tokens ni en los tres checkpoints de Laya.