Medições de velocidade e energia do Neural Engine
A reescrita FP16 para ANE melhora a velocidade de predição completa em 1.39× e a energia total estimada do sistema por decisão em 2.78× face ao MLX FP16 compilado. O candidato W8 K-means, validado em separado, alcança 1.42× e 3.19× respetivamente. Nenhum cumpre o objetivo de 10× pedido. Estes são resultados locais num M3 Max, com os limites de precisão e de medição de potência abaixo.
As experiências 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 multilingue de origem, mesmas oito variantes de estado de fatura, uma pergunta de quatro opções por pedido, 91 tokens reais preenchidos até 96. Sem cache de saída nem tokens gerados. Os três modelos permanecem residentes; o carregamento, a compilação e o aquecimento ficam fora dos intervalos medidos.
A linha de base ativa mx.compile, a cache de prefixos do prompt e buckets de
forma de 32 tokens. É mais rápida do que a linha de base histórica do MLX em
modo eager. O candidato ANE FP16 preserva os pesos originais, com um corpo
transformer Core ML completo, consulta de embedding no anfitrião e uma cauda de
ação FP32 na CPU. O W8 usa compressão de paleta apenas de pesos com K-means
agrupado, não aritmética W8A8; as suas ativações continuam em FP16 e a sua cauda
de ação no anfitrião continua em FP32.
| Métrica | MLX GPU FP16, compilado | ANE FP16 | ANE W8 K-means |
|---|---|---|---|
| Decisões concluídas | 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 da potência média total do sistema | 61.39 W | 30.75 W | 27.39 W |
| Energia total do sistema por decisão | 0.4288 J | 0.1540 J | 0.1344 J |
| Energia por decisão subtraindo o inativo | 0.3393 J | 0.0888 J | 0.0715 J |
| Ganho de velocidade face ao MLX compilado | 1× | 1.394× | 1.423× |
| Ganho de energia total do sistema face ao MLX compilado | 1× | 2.784× | 3.189× |
| Ganho de energia subtraindo o inativo face ao MLX compilado | 1× | 3.823× | 4.749× |
Os rácios usam médias do intervalo, incluindo todo o trabalho concluído:
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 novamente um rácio de energia pela velocidade conta o tempo decorrido duas vezes. A linha subtraindo o inativo usa uma fronteira de medição diferente; não significa que a potência de todo o portátil caia 3.8–4.7×. Estes são intervalos de débito saturado. Seria necessária uma experiência com taxa de pedidos igual para uma afirmação de potência a FPS fixo. O W8 melhora a velocidade média apenas cerca de 2.1% face ao FP16 nesta sessão, enquanto o seu pacote do corpo encolhe de 251.91 para 129.29 MB decimais. O tamanho do pacote exclui a tabela de embedding original do checkpoint/anfitrião e não é a memória total do runtime.
Cada implementação correu seis blocos de 20 segundos em três ciclos equilibrados
de MLX, ANE FP16, ANE W8, ANE W8, ANE FP16, MLX. Dez segundos de amostragem de
inatividade separam os blocos; os primeiros três segundos de inatividade são
descartados, e a potência de inatividade estabilizada adjacente é calculada em
média. Os intervalos de potência por bloco dos backends 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. Estavam
abertas outras aplicações de ambiente de trabalho; a alternância e a amostragem
de inatividade adjacente reduzem mas não eliminam a incerteza da carga em segundo
plano e do sensor.
Todas as 65,598 predições coincidem com a saída arredondada de aquecimento do respetivo backend para o estado correspondente. Os três backends selecionam a mesma resposta nestes oito estados. A suite de fidelidade separada é mais ampla: o FP16 L96 passa 59/59 perguntas compatíveis com um desvio máximo de probabilidade de 0.002925; o W8 passa essas mesmas 59 com um desvio de 0.014393 sob o gate inalterado de 0.02. O resultado completo de 63/63 pertence ao modelo FP16 L1024 exportado em separado. Estes são fixtures de regressão, não uma afirmação de exatidão geral na tarefa nem 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 registada do sistema foi 74.47 W. Nenhuma amostra foi descartada. O RSS por bloco é registado para o processo partilhado 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 impressões digitais do runtime e do pacote atuais são guardadas com o relatório.
Chamadas finais em bruto e amostras PSTR · Resumo auditado e intervalos bootstrap dentro da sessão
O anterior piloto apenas FP16 mediu
1.410× de velocidade e um ganho de energia total do sistema de 2.939×. É 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 final em bruto descrevia
inicialmente o piso histórico da soma de componentes do macmon de forma
incondicional; uma entrada adicional metadata_corrections esclarece que esta
execução usou apenas PSTR. Os campos originais e todas as medições são
preservados.
A compatibilidade do Snake é uma carga de trabalho separada
O mesmo planeador Snake publicado, os mesmos prompts compactos e a mesma política de segurança correram tanto no adaptador ANE FP16 como no MLX compilado, alternando a ordem de avaliação em estados ao vivo idênticos. As sementes 101 e 102 completaram cada uma 300 passos: 600/600 ações propostas e executadas coincidem, zero mortes e zero intervenções do escudo. As pontuações finais foram 9 e 10, com comprimentos de snake de 15 e 16. A diferença máxima de probabilidade de movimento foi 0.0036. Isto valida esta comparação de trajetórias FP16, não o comportamento do Snake com modelo comprimido nem a sobrevivência ilimitada.
| Semente | P50 / P95 de decisão completa ANE | P50 / P95 de decisão completa MLX compilado |
|---|---|---|
| 101 | 23.45 / 27.10 ms | 17.14 / 23.58 ms |
| 102 | 17.68 / 27.30 ms | 19.18 / 33.27 ms |
O adaptador ANE corre três perguntas sequencialmente em B1/L96; o MLX agrupa as três perguntas até L64. Estes tempos incluem características do planeador e predições completas, excluem o trabalho do outro backend, o passo de jogo e a renderização do terminal, e mostram uma variação substancial. Não estabelecem uma aceleração consistente do Snake nem uma taxa de renderização estável máxima. O resultado de 4.98 ms para uma única pergunta não pode ser publicitado como o tempo de fotograma completo do Snake. Uma exportação ANE B3/L64 dedicada seria uma tarefa separada de otimização e validação.
Estados, saídas e tempos em bruto 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 da telemetria
Cada chamada cronometrada inclui a construção do prompt, a tokenização, a construção de arrays, a consulta de embedding no anfitrião quando aplicável, a execução síncrona do modelo, as características de ação, a calibração e a formatação da saída. O MLX avalia as suas saídas lazy; o Core ML devolve arrays NumPy concluídos. Isto compara predições sem cache, não kernels de modelo isolados.
A comparação final usa o pequeno
amostrador apenas PSTR, sem privilégios. Fixa a
API SMC de baixo nível do macmon 0.8.2, abre uma ligação só de leitura e amostra o
valor original PSTR a cada 500 ms. Não lê os contadores de componentes do
IOReport. É uma estimativa do sensor de todo o sistema, não uma medição externa
de potência da tomada ou da bateria. O hash do executável e a proveniência do
código-fonte são registados com os resultados em bruto.
Este amostrador separado foi necessário porque a CLI oficial do macmon calcula
sys_power = max(PSTR, component_sum), como mostra o seu
código-fonte.
Os contadores de CPU e ANE devolviam normalmente zero neste SO, e depois uma
amostra saltou para aproximadamente 38,021 W de CPU e 2,068 W de ANE. O piso de
componentes propagou essa falha para uma leitura de sistema de 40,089 W. A causa
precisa da anomalia do IOReport está por resolver; o valor PSTR original não pode
ser recuperado a partir dessa amostra. Toda a execução de energia afetada foi
rejeitada, sem remover nem limitar a amostra má. O seu
registo em bruto
continua disponível, mas os seus agregados de energia guardados não podem ser
usados como resultados.
A execução anterior apenas FP16 usou a versão oficial do macmon v0.8.2, cujo
SHA256 do arquivo foi verificado como
588d5bde79885ba36f693e5150911c10c3ad208a2e418a3f2aa827ac84a2d973.
Passou as verificações de sanidade posteriores e continua a ser evidência
histórica. A execução final apenas PSTR mede novamente todos os backends com um
único amostrador consistente.
O harness integra watts ao longo de timestamps monotónicos de receção com
fronteiras interpoladas. Leituras de sistema em falta, 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 folgada para este M3 Max, não um limite de exatidão
calibrado. Intervalos acima de max(2 seconds, 3 × sample interval) também
rejeitam a execução. O resumo verifica ciclos equilibrados completos, estabilidade
por chamada, contagens de chamadas, energia ativa, ambos os intervalos de
inatividade adjacentes e a energia resultante subtraindo o inativo, tudo face às
amostras em bruto. A energia incremental mantém o seu sinal; nunca é limitada
para fabricar um rácio grande.
O amostrador direto omite os campos de potência da CPU/GPU/ANE porque não os mede. Contadores de componentes históricos em falta ou a zero não podem estabelecer energia zero nem a ausência de execução no ANE. O bootstrap reamostra ciclos equilibrados completos; três ciclos de uma sessão de ambiente de trabalho não caracterizam toda a carga em segundo plano, execuções futuras ou a exatidão do sensor. Nenhum dos rácios medidos está perto de 10×.
O Neural Engine executa realmente trabalho?
O plano de cálculo Core ML do grafo B1/L96 reescrito coloca todas as 6,390
operações não constantes em MLNeuralEngineComputeDevice; as restantes 3,809
entradas desconhecidas são constantes. Isto é uma colocação prevista, não prova
de hardware suficiente por si só. A exportação SDPA normal não tinha operações
preferidas pelo NE neste sistema.
Um traço Instruments Core ML separado de 15.97 segundos, capturado enquanto o
candidato corria com CPU_AND_NE, registou 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 fornece, por isso, provas positivas de
atividade do ANE em runtime, além do plano de cálculo. A tabela é global e não
associa um PID nem uma identidade de modelo a cada predição; a tabela de sinais de
modelo do Core ML estava vazia nesta gravação. Não atribuímos todos os intervalos
de hardware exclusivamente ao Laya nem afirmamos que o trabalho do anfitrião corre
no ANE.
Eventos de hardware na lista de permitidos
incluem apenas timestamps, duração, dispositivo, etiqueta e estado. Os arquivos
Instruments completos e os metadados do ambiente do processo ficam no diretório
artifacts/, que é 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.
Reproduzir
Primeiro cria e valida os pacotes fixos L96 FP16 e W8 K-means com os comandos em
o relatório de engenharia. Esses comandos escrevem em
diretórios novos sob artifacts/ane-repro/. Compila o amostrador direto do sensor
localmente; não é instalado nenhum daemon de sistema nem serviço com privilégios.
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 do runtime, inicia benchmarks.trace_ane, espera
pelo seu ficheiro PID de prontidão e depois associa o Instruments sem outra carga
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 curta não estabelece desempenho a 512/1024 tokens nem em todos os três checkpoints do Laya.