Medições de velocidade e energia do Neural Engine
A reescrita ANE FP16 melhora a velocidade de predição completa em 1.39× e a energia de sistema inteiro por decisão estimada em 2.78× em relação ao MLX FP16 compilado. O candidato W8 K-means validado separadamente alcança 1.42× e 3.19×, respectivamente. Nenhum dos dois atinge a meta de 10× solicitada. Esses são resultados locais no M3 Max, com os limites de precisão e de medição de potência abaixo.
Os experimentos de implementação e conversão estão em ANE_ENGINEERING.md; os limites matemáticos e os contratos de fidelidade estão em ANE_MATH.md.
Comparação final sustentada de decisões curtas
M3 Max, 40 núcleos de GPU, 128 GiB, macOS 27.2. Mesmo checkpoint multilíngue de origem, mesmas oito variantes de estado de fatura, uma pergunta de quatro opções por requisição, 91 tokens reais preenchidos até 96. Sem cache de saída nem tokens gerados. Os três modelos permanecem residentes; carregamento, compilação e aquecimento ficam fora dos intervalos medidos.
A linha de base habilita mx.compile, cache de prefixo de prompt e buckets de forma de 32
tokens. Ela é mais rápida do que a linha de base histórica do MLX em modo eager. O candidato FP16 ANE
preserva os pesos originais, com um corpo transformer Core ML completo,
lookup de embedding no host e cauda de ação na CPU em FP32. O W8 usa compressão de paleta
somente de pesos com K-means agrupado, não aritmética W8A8; suas ativações ainda
usam FP16 e sua cauda de ação no host permanece FP32.
| Métrica | MLX GPU FP16, compilado | ANE FP16 | ANE W8 K-means |
|---|---|---|---|
| Decisões completadas | 17,184 | 23,961 | 24,453 |
| Duração ativa medida | 120.02 s | 120.02 s | 120.02 s |
| P50 ponta a ponta | 6.937 ms | 4.976 ms | 4.879 ms |
| P95 ponta a ponta | 7.393 ms | 5.307 ms | 5.227 ms |
| Tempo médio decorrido por decisão | 6.984 ms | 5.009 ms | 4.908 ms |
| Estimativa de potência média do sistema inteiro | 61.39 W | 30.75 W | 27.39 W |
| Energia de sistema inteiro por decisão | 0.4288 J | 0.1540 J | 0.1344 J |
| Energia por decisão com idle subtraído | 0.3393 J | 0.0888 J | 0.0715 J |
| Ganho de velocidade vs MLX compilado | 1× | 1.394× | 1.423× |
| Ganho de energia do sistema inteiro vs MLX compilado | 1× | 2.784× | 3.189× |
| Ganho de energia com idle subtraído vs MLX compilado | 1× | 3.823× | 4.749× |
As razões usam médias de intervalo, incluindo todo o trabalho 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 uma razão de energia pela velocidade de novo conta o tempo decorrido duas vezes. A linha com idle subtraído usa uma fronteira de medição diferente; ela não significa que a potência do laptop inteiro cai 3.8–4.7×. Esses são intervalos de throughput saturado. Um experimento de taxa de requisições igual seria necessário para uma afirmação de potência a FPS fixo. O W8 melhora a velocidade média em apenas cerca de 2.1% sobre o FP16 nesta sessão, enquanto seu pacote de corpo encolhe de 251.91 para 129.29 MB decimais. O tamanho do pacote exclui a tabela de embedding do checkpoint/host original e não é a memória total de runtime.
Cada implementação rodou seis blocos de 20 segundos em três ciclos balanceados de
MLX, ANE FP16, ANE W8, ANE W8, ANE FP16, MLX. Dez segundos de amostragem em idle separam
os blocos; os primeiros três segundos em idle são descartados, e a potência de idle estabilizada adjacente
é calculada em média. As faixas de potência por bloco de backend foram 60.32–62.38 W para o MLX,
29.28–35.14 W para o ANE FP16 e 26.68–27.95 W para o ANE W8. Outros aplicativos de desktop
estavam abertos; a alternância e a amostragem de idle adjacente reduzem, mas não eliminam
a incerteza de carga de fundo e de sensor.
Todas as 65,598 predições correspondem à saída arredondada de aquecimento de seu backend para o estado correspondente. Os três backends selecionam a mesma resposta nesses oito estados. A suíte de fidelidade separada é mais ampla: o FP16 L96 passa em 59/59 perguntas de ajuste com desvio máximo de probabilidade de 0.002925; o W8 passa nessas mesmas 59 com desvio de 0.014393 sob o limiar inalterado de 0.02. O resultado completo de 63/63 pertence ao modelo FP16 L1024 exportado separadamente. Essas são fixtures de regressão, não uma afirmação de acurácia geral de tarefa ou de calibração preservada em entradas arbitrárias.
A execução reteve 1,101 amostras de potência; o intervalo máximo foi de 0.510 segundos e a potência máxima registrada do sistema foi de 74.47 W. Nenhuma amostra foi descartada. O RSS por bloco é registrado para o processo compartilhado com todos os modelos e buffers de gravação residentes; esses valores não podem ser atribuídos à memória de modelo de um backend individual. As fingerprints atuais do runtime e do pacote são armazenadas com o relatório.
Chamadas brutas finais e amostras PSTR · Resumo auditado e intervalos bootstrap dentro da sessão
O piloto anterior somente FP16 mediu
1.410× de velocidade e 2.939× de ganho bruto de energia do sistema. Ele é anterior às últimas verificações de entrada
e à instrumentação de estabilidade por chamada; a nova execução de três braços acima é a
comparação publicada para o runtime final. Uma ressalva de metadados no relatório bruto
final descrevia inicialmente o piso histórico de soma de componentes do macmon de forma incondicional;
uma entrada aditiva de metadata_corrections esclarece que esta execução usou apenas PSTR.
Os campos originais e todas as medições são preservados.
A compatibilidade com o Snake é uma carga de trabalho separada
O mesmo planejador de Snake publicado, os prompts compactos e a política de segurança rodaram tanto no adapter ANE FP16 quanto no MLX compilado, alternando a ordem de avaliação em estados ao vivo idênticos. As sementes 101 e 102 completaram 300 passos cada: 600/600 ações propostas e executadas concordam, zero mortes e zero intervenções de escudo. As pontuações finais foram 9 e 10, com comprimentos de cobra 15 e 16. A diferença máxima de probabilidade de movimento foi 0.0036. Isso valida esta comparação de trajetória em FP16, não o comportamento de Snake com modelo comprimido nem a sobrevivência ilimitada.
| Semente | Decisão completa ANE P50 / P95 | Decisão completa 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 |
O adapter ANE roda três perguntas sequencialmente em B1/L96; o MLX faz batching das três perguntas em até L64. Essas medições incluem recursos do planejador e predições completas, excluem o trabalho do outro backend, o passo do jogo e a renderização do terminal, e mostram variação substancial. Elas não estabelecem uma aceleração consistente do Snake nem uma taxa máxima de renderização estável. O resultado de 4.98 ms para uma única pergunta não deve ser anunciado como o tempo completo de quadro do Snake. Uma exportação ANE B3/L64 dedicada seria uma tarefa separada de otimização e validação.
Estados, saídas e medições de tempo brutos do 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
Fronteira de medição e limitações de telemetria
Toda chamada cronometrada inclui construção do prompt, tokenização, construção de arrays, lookup de embedding no host quando aplicável, execução síncrona do modelo, recursos de ação, calibração e formatação da saída. O MLX avalia suas saídas lazy; o Core ML retorna arrays NumPy completos. Isso compara predições sem cache, não kernels de modelo isolados.
A comparação final usa o pequeno e sem privilégios
amostrador somente PSTR. Ele fixa a API SMC
de baixo nível do macmon 0.8.2, abre uma conexão somente leitura e amostra o valor PSTR
original a cada 500 ms. Ele não lê os contadores de componentes do IOReport. Esta é
uma estimativa de sensor de sistema inteiro, não uma medição externa de potência de parede ou de bateria.
O hash do executável e a proveniência da origem são registrados com os resultados brutos.
Esse amostrador separado foi necessário porque a CLI oficial do macmon calcula
sys_power = max(PSTR, component_sum), como mostrado em seu
código-fonte.
Os contadores de CPU e ANE normalmente retornavam zero neste sistema operacional, então uma amostra saltou para
aproximadamente 38,021 W de CPU e 2,068 W de ANE. O piso dos componentes propagou essa
falha para uma leitura de sistema de 40,089 W. A causa precisa da anomalia do IOReport
não foi resolvida; o valor PSTR original não pode ser recuperado dessa amostra.
Toda a execução de energia afetada foi rejeitada, sem remover nem cortar
a amostra ruim. Seu registro bruto
permanece disponível, mas seus agregados de energia armazenados não devem ser usados como resultados.
A execução anterior somente FP16 usou o lançamento oficial do macmon v0.8.2, cujo SHA256 do
arquivo foi verificado como
588d5bde79885ba36f693e5150911c10c3ad208a2e418a3f2aa827ac84a2d973.
Ele passou nas verificações de sanidade posteriores e permanece como evidência histórica. A execução final
somente PSTR mede todos os backends de novo com um amostrador consistente.
O harness integra watts ao longo de carimbos de tempo de recebimento monotônicos com fronteiras
interpoladas. Leituras de sistema ausentes, não positivas, não finitas ou acima de 500 W rejeitam
a execução. O teto de 500 W é uma verificação de sanidade deliberadamente frouxa para este M3 Max,
não um limite calibrado de precisão. Intervalos acima de max(2 seconds, 3 × sample interval)
também rejeitam a execução. O resumo verifica ciclos balanceados completos, estabilidade por
chamada, contagens de chamadas, energia ativa, os dois intervalos de idle adjacentes e a
energia resultante com idle subtraído em relação às amostras brutas. A energia incremental
mantém seu sinal; ela nunca é limitada para fabricar uma razão grande.
O amostrador direto omite os campos de potência de CPU/GPU/ANE porque não os mede. Contadores de componentes históricos ausentes ou zerados não podem estabelecer energia zero nem a ausência de execução no ANE. O bootstrap reamostra ciclos balanceados completos; três ciclos de uma sessão de desktop não caracterizam toda a carga de fundo, execuções futuras ou a precisão do sensor. Nenhuma das razões medidas chega perto de 10×.
O Neural Engine de fato executa trabalho?
O compute plan do Core ML do grafo B1/L96 reescrito coloca todas as 6,390 operações não
constantes em MLNeuralEngineComputeDevice; as 3,809 entradas desconhecidas restantes
são constantes. Isso é posicionamento previsto, não evidência de hardware suficiente
por si só. A exportação SDPA comum não tinha operações preferidas por NE neste sistema.
Um trace separado de 15.97 segundos do Instruments Core ML, obtido enquanto o candidato
rodava com CPU_AND_NE, capturou 3,124 intervalos ativos de “Neural Engine Prediction”
e um carregamento de modelo de sistema em cache não relacionado. A tabela de hardware exportada
portanto fornece evidência positiva de atividade do ANE em tempo de execução, além do compute plan.
A tabela é global e não anexa um PID ou identidade de modelo a cada predição;
a tabela de signposts de modelo do Core ML estava vazia nesta gravação. Não atribuímos
cada intervalo de hardware exclusivamente ao Laya nem afirmamos que o trabalho do host roda no ANE.
Eventos de hardware na allowlist
incluem apenas carimbos de tempo, duração, dispositivo, rótulo e estado. Os arquivos completos do Instruments
e os metadados do ambiente do processo permanecem no diretório artifacts/ ignorado.
O tracing foi separado do teste de energia, e os intervalos de hardware instrumentados
não são usados como o resultado de latência ponta a ponta.
Reproduza
Primeiro crie e valide os pacotes fixos L96 FP16 e W8 K-means com os
comandos em o relatório de engenharia. Esses comandos gravam
em diretórios novos sob artifacts/ane-repro/. Compile o amostrador direto de sensor
localmente; nenhum daemon de sistema ou serviço privilegiado é instalado.
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 independentes de runtime, inicie benchmarks.trace_ane, aguarde seu
arquivo de PID pronto e então anexe o Instruments sem outra carga de trabalho de modelo em execução:
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
O checkpoint original e a exportação mais curta têm limites de contexto separados. O runtime L96 rejeita entradas que não cabem; um resultado de velocidade de carga de trabalho curta não estabelece desempenho em 512/1024 tokens nem nos três checkpoints do Laya.