Otimizando a inferência no dispositivo para Apple Silicon
Um motor local personalizado que melhora a taxa de transferência de preenchimento e decodificação.
Para que essa divisão do trabalho pareça perfeita, a inferência local precisa acompanhar o ritmo do restante da tarefa. Isso exige um motor capaz de processar prompts rapidamente e sustentar uma alta taxa de geração de tokens.
Lily, o nosso motor de inferência local e leve, foi criado especificamente para Apple Silicon e Qwen3.6-35B-A3B, com otimizações separadas para pré-preenchimento e decodificação. Uma demonstração autónoma está publicamente disponível no GitHub.
Introdução
Uma maneira comum de executar LLMs em um Mac é utilizando o MLX, a estrutura de aprendizado de máquina de código aberto da Apple para o Apple Silicon. Sua biblioteca complementar, MLX-LM, adiciona os componentes necessários para carregar e gerar texto com uma ampla variedade de modelos de linguagem. Juntos, o MLX e o MLX-LM fornecem uma pilha pronta para uso e de uso geral para inferência local de LLMs.
O Qwen3.6-35B-A3B é um modelo híbrido esparso: ele utiliza roteamento por mistura de especialistas (MoE) e combina estados recorrentes de tamanho fixo com atenção completa. Essas escolhas arquitetônicas reduzem a quantidade de computação necessária, mas também geram cargas de trabalho irregulares. Os tokens são direcionados para diferentes pesos de especialistas, e os estados recorrentes têm natureza sequencial.
O MLX-LM já seleciona kernels otimizados para as fases de inferência e formatos comuns de carga de trabalho, mas suas operações reutilizáveis precisam dar suporte a muitas arquiteturas de modelo. Um motor dedicado ao Qwen pode se especializar no nível do modelo e do tempo de execução, coordenando kernels, movimentação de dados e agendamento em torno da estrutura fixa do modelo.
O Lily implementa essa especialização de ponta a ponta em um único processo. Um tempo de execução em Rust carrega o ponto de verificação do modelo e gerencia o estado da sessão e o loop de geração; uma API de conclusão de chat compatível com a OpenAI aceita solicitações e transmite tokens; e kernels Metal personalizados executam operações específicas do Qwen. Nem o PyTorch nem o MLX estão no caminho de execução.
Medimos o desempenho de preenchimento e decodificação separadamente. A taxa de transferência de preenchimento captura a rapidez com que o motor processa o prompt; a taxa de transferência de decodificação captura a rapidez com que ele gera tokens de saída.
Medimos o Qwen3.6-35B-A3B em um único MacBook Pro equipado com um M5 Max, uma GPU de 40 núcleos e 128 GB de memória unificada. Em dez comprimentos de prompt para o prefill e dez comprimentos de contexto para a decodificação, de 256 a 128K tokens (K = 1.024), o mecanismo apresenta em média 1,22× a taxa de throughput de prefill do MLX-LM e 1,32× seu throughput de decodificação. Em um prompt de 4K tokens e um contexto de decodificação de 4K tokens, o mecanismo personalizado atinge 5.749,9 tokens por segundo de prefill e 186,6 tokens por segundo de decodificação, em comparação com 4.737,5 e 140,9 no MLX-LM. Em uma sessão com várias interações, essas economias de tempo se acumulam a cada chamada adicional ao modelo.
A seguir, explicamos como a arquitetura do Qwen cria oportunidades de otimização específicas do modelo no Apple Silicon. Em seguida, detalhamos as alterações resultantes no preenchimento e na decodificação. Também abordamos em que ponto a otimização adicional deixa de compensar, antes de encerrar com uma comparação de ponta a ponta com o MLX-LM.
Oportunidades de otimização específicas do Qwen no Apple Silicon
O Qwen cria três formas de carga de trabalho distintas
O Qwen3.6-35B-A3B contém 35 bilhões de parâmetros, mas ativa apenas cerca de 3 bilhões para cada token. Um roteador pontua 256 subredes de especialistas e seleciona oito, juntamente com um especialista compartilhado que processa cada token. Esse design de MoE esparso reduz a computação, mas produz trabalho desigual: os especialistas recebem números diferentes de tokens, e cada token exige pesos de uma combinação diferente de especialistas.
O Qwen também combina 10 camadas de atenção completa com 30 camadas do Gated DeltaNet. Esses dois tipos de camadas retêm informações anteriores de maneiras diferentes.
As camadas de atenção utilizam atenção de consulta agrupada (GQA). O Qwen possui 16 cabeças de consulta e duas cabeças de chave-valor (KV), com oito cabeças de consulta compartilhando cada cabeça de KV. O compartilhamento torna o cache de KV menor e permite que os dados em cache sejam reutilizados entre as cabeças de consulta. O cache ainda armazena novas chaves e novos valores para cada token, de modo que cada etapa de decodificação lê mais dados à medida que o contexto cresce.
Em vez disso, o Gated DeltaNet compacta informações anteriores em um estado recorrente de tamanho fixo. Um portão aprendido controla quanto do estado existente deve ser retido, enquanto uma atualização delta incorpora informações do token atual. O modelo define essas atualizações de forma recorrente, de modo que cada token depende do estado produzido pelo token anterior. No entanto, durante o preenchimento, um motor pode avaliar o mesmo cálculo de duas maneiras. Ele pode examinar os tokens diretamente enquanto carrega o estado adiante, ou reorganizar as atualizações em blocos que expõem mais operações de matrizes e paralelismo em nível de token. Qual abordagem é mais rápida depende das dimensões do modelo, da carga de trabalho e do hardware.
Juntas, essas estruturas criam três padrões computacionais: grupos de especialistas desiguais, atenção sobre um cache em crescimento e uma recorrência de tamanho fixo que pode ser avaliada diretamente ou em blocos.
O Apple Silicon fornece caminhos diferentes para diferentes cargas de trabalho
O preenchimento processa várias linhas de ativação de tokens de prompt de uma só vez. A carga de trabalho local considerada aqui normalmente decodifica uma solicitação por vez (lote 1) e processa uma nova linha por etapa. Essa diferença altera a forma como os mesmos pesos do modelo são utilizados. O preenchimento pode reutilizar cada bloco de pesos em centenas ou milhares de linhas. A decodificação, em sua maior parte, não pode fazer isso, pois cada novo token exige outra passagem pelos pesos.
O Apple Silicon coloca a CPU e a GPU atrás de uma memória unificada, um único pool de memória física acessível a ambas. Isso permite que o modelo permaneça residente sem manter uma cópia separada na GPU, mas não torna a movimentação de dados gratuita. A leitura de pesos e valores intermediários ainda consome largura de banda da memória, enquanto os registradores e outros armazenamentos no chip são mais rápidos, porém muito menores.
A GPU M5 também fornece caminhos de computação diferentes. As camadas lineares do preenchimento utilizam multiplicação geral de matriz-matriz (GEMM), aplicando uma matriz de pesos a várias linhas de uma só vez. GEMMs compatíveis podem utilizar o Acelerador Neural em cada núcleo da GPU por meio de operações de tensor do Metal 4. A decodificação em lote 1, por sua vez, utiliza multiplicação geral de matriz-vetor (GEMV), aplicando os mesmos pesos a uma linha. Com pouca reutilização de pesos, a GEMV é limitada principalmente pela largura de banda da memória e é mais adequada para as unidades lógicas aritméticas (ALUs) vetoriais da GPU do que para os Aceleradores Neurais projetados para operações de matrizes com maior reutilização de dados.
Esses caminhos de execução não são exclusivos do Lily. O MLX opera sobre a mesma memória unificada e seleciona kernels otimizados de matriz e vetor de acordo com a forma da carga de trabalho. A implementação do Qwen no MLX-LM já agrupa o trabalho de especialistas, avalia o Gated DeltaNet com um kernel Metal recorrente fundido e utiliza atenção consciente de GQA. Esses recursos são o ponto de partida compartilhado para uma inferência eficiente do Qwen no Apple Silicon.
Estratégia de otimização
O escopo mais restrito do Lily permite coordenar esses caminhos de execução compartilhados em torno da arquitetura e das dimensões exatas do Qwen. Ele utiliza caminhos de GPU específicos para cada fase, mapeia as cargas de trabalho de especialistas, recorrentes e de atenção do Qwen para minimizar a movimentação de dados e seleciona kernels e layouts com base na forma da carga de trabalho medida. A estratégia tem três partes:
- Adaptar o caminho da GPU à fase de inferência. Utilizar execução orientada a matrizes quando o preenchimento puder reutilizar pesos em várias linhas, e execução orientada a vetores quando a decodificação em lote 1 processar uma linha por vez.
- Mapear a estrutura do Qwen para a GPU, minimizando a movimentação de dados. Manter os pesos compactados até que sejam utilizados, organizar o trabalho de especialistas roteados sem retornar à CPU, reter o estado do Gated DeltaNet no chip durante sua varredura recorrente e reutilizar os dados de KV compartilhados pela atenção de consulta agrupada.
- Adaptar os kernels à forma da carga de trabalho. Em cada fase, selecione tamanhos de blocos, layouts de execução e caminhos de atenção a partir da contagem de linhas disponível, da distribuição das linhas entre os especialistas, das dimensões da operação e do comprimento atual do contexto.
As seções a seguir explicam essas escolhas. Para as otimizações avaliadas em ablações correspondentes em um M5 Max, estimamos seus efeitos comparando configurações de motor idênticas, exceto pela otimização em estudo. Como esses experimentos comparam versões do nosso motor entre si, eles explicam os mecanismos em vez de decompor os resultados finais em relação ao MLX-LM.
Preenchimento: reutilizar pesos e manter o roteamento na GPU
O preenchimento expõe muitas linhas de tokens de uma só vez, mas o Qwen direciona essas linhas de forma desigual entre os especialistas e atualiza o estado recorrente ao longo da sequência. Suas otimizações dividem-se em três grupos: organizar o trabalho esparso de especialistas em torno das linhas roteadas, manter a varredura do Gated DeltaNet no chip e dividir prompts longos em trechos delimitados.
Otimizar a computação esparsa de especialistas
Dequantizar pesos durante a multiplicação de matrizes
O ponto de verificação do Qwen3.6-35B-A3B utiliza quantização afim de 4 bits por grupo. Cada peso é armazenado como um código inteiro de 4 bits, enquanto cada grupo de 64 pesos compartilha uma escala e um viés em bfloat16 usados para reconstruir seus valores. Isso reduz o modelo de 35 bilhões de parâmetros de aproximadamente 70 GB de pesos em bfloat16 para um ponto de verificação de 19,4 GB, tornando prático manter o modelo residente no Mac.
A operação de tensor do Metal 4 utilizada para a multiplicação de matrizes consome operandos em bfloat16 em vez da representação compactada de 4 bits. Antes da multiplicação, a GPU deve reconstruir os pesos em bfloat16. A GEMV agrupada otimizada no Lily realiza essa conversão um pequeno bloco de pesos por vez e mantém o resultado na memória de threadgroup no chip apenas pelo tempo necessário para multiplicá-lo pelas linhas de ativação roteadas. A acumulação utiliza ponto flutuante de 32 bits, e a saída é gravada em bfloat16. O array de pesos expandido completo nunca é criado na memória unificada.
Na ablação, a dequantização é executada como uma operação separada: ela expande os pesos de 4 bits em um array bfloat16 na memória unificada, após o que o kernel de matriz lê esse array de volta. Com um prompt de 512 tokens, mover a dequantização para a GEMV agrupada aumentou a taxa de transferência de preenchimento de ponta a ponta em 77,4% ao eliminar essa gravação e leitura intermediárias.
Manter o roteamento de especialistas na GPU
A GEMV agrupada precisa que as linhas de ativação atribuídas a cada especialista sejam armazenadas juntas. Após selecionar oito especialistas por token, um histograma conta quantas atribuições foram destinadas a cada especialista. Uma varredura de prefixo transforma essas contagens em deslocamentos iniciais, uma etapa de dispersão posiciona as linhas em seus grupos de especialistas, e um mapa de blocos lista os blocos de matrizes de tamanho fixo que a GEMV agrupada deve processar.
O caminho otimizado mantém toda essa sequência em um único buffer de comando — um lote ordenado de operações de GPU — para cada trecho de prompt. Em vez disso, uma ablação faz uma pausa para que a CPU possa inspecionar os intermediários de roteamento e enviar a operação seguinte. Manter o histograma e a varredura de prefixo na GPU adiciona dois kernels, mas remove a sincronização entre CPU e GPU dentro de cada camada de MoE.
Com um prompt de 512 tokens, habilitar o roteamento residente na GPU aumentou o preenchimento de ponta a ponta em 89%. Isso também demonstra por que a contagem de kernels isoladamente pode ser enganosa: a rota mais rápida inicia mais kernels, mas nunca aguarda a CPU dentro da camada.
Igualar o tamanho do bloco à carga do especialista
Com um prompt de 2 mil tokens, o roteamento de cada token para oito de 256 especialistas produz 16.384 atribuições de token-especialista, ou uma média de 64 linhas de ativação por especialista. A distribuição real é irregular: alguns especialistas recebem muitas linhas, enquanto outros recebem poucas.
A GEMV agrupada divide a saída de cada especialista em blocos, que são pequenos blocos retangulares da saída de uma multiplicação de matrizes. Cada bloco é atribuído a um threadgroup de GPU. Nas GPUs do Apple Silicon, um threadgroup contém um ou mais simdgroups, cada um consistindo em 32 tópicos que executam instruções em passo sincronizado.
Blocos maiores distribuem o custo de configuração entre mais linhas e expõem mais trabalho paralelo, mas parte de um bloco grande permanece ociosa quando um especialista recebe apenas algumas linhas. O tamanho do bloco e a contagem de simdgroups estão, portanto, acoplados.
Uma ablação fixa o bloco em 16 linhas. Em relação a esse controle, habilitar o bloco de 32 linhas com quatro simdgroups melhorou o preenchimento de ponta a ponta em 13,2% com 2 mil tokens.
Manter o estado recorrente no chip
Durante o preenchimento, cada camada do Gated DeltaNet examina o prompt em ordem enquanto carrega seu estado recorrente adiante. Com a residência em registradores desativada, a ablação utiliza uma varredura baseada em blocos. Com um prompt de 2 mil tokens, esse caminho movimenta 256 MiB (mebibytes) de estado por camada e interrompe repetidamente os tópicos cooperantes em barreiras, que são pontos de sincronização onde todos os tópicos participantes devem aguardar uns pelos outros.
O estado recorrente é uma matriz. O kernel otimizado atribui cada coluna a um simdgroup. O simdgroup divide a coluna entre seus tópicos, carrega a coluna em seus registradores uma única vez e conduz o estado por toda a varredura. Os tópicos trocam resultados intermediários por meio de operações de simdgroup em vez de memória de threadgroup, que é o armazenamento no chip compartilhado entre um threadgroup. O estado concluído é gravado de volta apenas após a varredura.
O estado e seu portão utilizam um formato de ponto flutuante de 32 bits porque pequenos erros de arredondamento se acumulam em atualizações sequenciais. As ativações de consulta e chave permanecem em bfloat16.
Com um prompt de 2 mil tokens, habilitar a varredura residente em registradores melhorou o preenchimento de ponta a ponta em 5,6%. As GEMMs de especialistas responderam por cerca de 90% do tempo de preenchimento. A varredura sequencial não expõe trabalho matricial reutilizável suficiente para se beneficiar dos Aceleradores Neurais.
Delimitar a memória temporária com a divisão de prompts em trechos
O tempo de execução processa um prompt longo como uma sequência de trechos delimitados, em vez de manter dados temporários para cada token de prompt na memória ao mesmo tempo. Os pesos do modelo permanecem residentes na memória unificada, enquanto o estado recorrente e o cache de KV transportam o contexto de um trecho para o seguinte. Nenhum contexto anterior é descartado.
Sem a divisão em trechos, os arrays de ativação temporários crescem com o prompt completo e competem com os pesos do modelo, o estado recorrente e o cache de KV pela memória unificada. A divisão em trechos mantém ativos os valores temporários de apenas um segmento por vez, liberando ou reutilizando esse armazenamento antes de processar o segmento seguinte. Isso limita a memória de trabalho de pico e permite que o motor processe prompts mais longos sem alterar a saída do modelo.
O preenchimento dividido em trechos é popular em muitos motores e é crucial para atender a longas trajetórias de vários turnos nesses ambientes com restrição de memória. O tempo total de preenchimento para camadas de atenção permanece quadrático em relação ao comprimento do prompt, com alguma sobrecarga adicional gerada por carregamentos repetidos de KV de trechos anteriores.
Decodificação: minimize os bytes movimentados por token
A decodificação em lote 1 processa uma nova linha de cada vez. Com pouca reutilização de pesos, sua taxa de transferência depende principalmente de quantos bytes o motor movimenta para cada token. As alterações na decodificação dividem-se em quatro grupos: otimizar o caminho de peso de linha única, manter cada etapa na GPU, reduzir o tráfego intermediário e de estado, e ler o cache de atenção de forma eficiente.
Otimizar o caminho de peso de linha única
O MLX já despacha o trabalho de linha única para kernels especializados de matriz-vetor. Como o Lily não utiliza o MLX, o tempo de execução personalizado deve fornecer a mesma estratégia básica. Nossa GEMV paralela a linhas foi projetada para uma linha de ativação. Um simdgroup coopera na saída enquanto lê diferentes partes da matriz de pesos em paralelo.
Manter cada etapa de decodificação na GPU
Manter a transferência de tokens na GPU
Cada etapa de decodificação termina selecionando o próximo token; a etapa seguinte começa com esse token como entrada. Enviar a seleção para a CPU e, em seguida, de volta para a GPU adiciona um ponto de sincronização a cada token. Nosso tempo de execução alterna entre dois buffers de comando e dois slots de token residentes na GPU. A GPU seleciona o token com a pontuação mais alta e grava seu ID de token diretamente no slot de entrada para a próxima etapa de decodificação, enquanto a CPU prepara o trabalho subsequente.
Sobrepor trabalhos independentes na GPU
Em uma etapa de decodificação em lote 1 registrada, a geração de um token acionou 795 kernels de GPU. Suas dependências formaram 555 estágios sequenciais, deixando alguns kernels livres para serem executados simultaneamente. No entanto, o modo de execução serial do Metal executou todos os kernels em ordem.
O caminho de decodificação otimizado registra as dependências reais de dados em uma passagem concorrente do Metal. Inicializações de kernels independentes podem ser executadas ao mesmo tempo quando os recursos da GPU permitirem. Uma barreira é inserida apenas quando um trabalho posterior exigir um resultado anterior.
Reduzir o tráfego intermediário e de estado
Kernels separados frequentemente materializam um intermediário: um kernel grava um resultado temporário na memória e o seguinte lê o resultado de volta. O caminho de decodificação otimizado funde quatro cadeias: as duas projeções de entrada de especialistas com sua ativação com portão; a projeção de saída do especialista com sua pontuação de roteamento e o resultado do especialista compartilhado; a preparação de consulta e chave antes da atenção; e a atualização recorrente com sua normalização. Cada kernel fundido mantém valores temporários em registradores em vez de enviá-los pela memória.
A fusão também encurta o grafo de dependência: quando uma gravação intermediária desaparece, o mesmo acontece com a barreira que protegia seu consumidor.
Leia o cache de atenção de forma eficiente
Coalescer leituras do cache de atenção
A atenção lê chaves e valores do cache de KV durante cada etapa de decodificação. Na ablação, tópicos de GPU vizinhos nem sempre solicitam bytes vizinhos, forçando o sistema de memória a atender a mais transações separadas. Habilitar carregamentos coalescentes faz com que tópicos adjacentes solicitem bytes adjacentes para que o hardware possa combinar suas leituras.
Na configuração bfloat16, a coalescência aumentou a largura de banda de chave de 33,8 para 47,9 GB/s, elevou a largura de banda de valor de 42,0 para 61,8 GB/s e melhorou a decodificação de ponta a ponta em 2,1% em um contexto de 3.840 tokens.
Empacotar cabeças de consulta para reutilizar linhas de KV
A atenção de consulta agrupada permite que oito cabeças de consulta compartilhem uma cabeça de KV. Na ablação, cada cabeça de consulta é executada em um simdgroup separado, de modo que todas as oito solicitam independentemente a mesma linha de KV em cache. O kernel otimizado agrupa quatro cabeças de consulta em um threadgroup, que carrega cada linha de KV uma vez e a reutiliza em quatro cálculos de atenção. Um segundo threadgroup lida com as quatro cabeças restantes.
Essa técnica, comumente chamada de empacotamento GQA, executa a mesma aritmética e produz bytes de saída idênticos, enquanto reduz oito solicitações de KV independentes a dois carregamentos compartilhados. Em comparação com a ablação desempacotada, ela melhorou a taxa de transferência de decodificação de ponta a ponta em 23,8% em um contexto de 32 mil tokens.
Alternar layouts de atenção em contextos longos
Cada etapa de decodificação em uma camada de atenção completa examina o cache de KV existente. Um layout de bloco fixo divide esse cache em partes iguais que a GPU pode processar em paralelo. Seu agendamento extra não compensa quando o cache é pequeno, mas o layout de bloco fixo equilibra o trabalho de forma mais uniforme à medida que o contexto cresce.
Para este modelo, o tempo de execução mantém o caminho geral de atenção abaixo de 32 mil tokens e utiliza o caminho de bloco fixo em 32 mil tokens ou mais. A troca se aplica quando cada cabeça possui 256 valores e oito cabeças de consulta compartilham uma cabeça de KV; outras formas permanecem no caminho geral. Uma ablação desativa essa troca e utiliza sempre o caminho geral. Habilitar a rota de bloco fixo melhorou a decodificação de ponta a ponta em 7,7% a 32K, 27,4% a 64K e 40,2% a 128K.
Limites de otimização adicional
Algumas alterações melhoraram uma operação isolada, mas não a inferência de ponta a ponta.
A decodificação especulativa, que utiliza um modelo menor para propor tokens para o modelo completo verificar, tornou a decodificação em lote 1 18% mais lenta. A verificação processou grupos de duas a cinco linhas, um formato ineficiente para este hardware, e as linhas frequentemente selecionavam especialistas diferentes, aumentando a quantidade de dados de pesos de especialistas lidos. A redução do vocabulário de saída do redator melhorou a taxa de transferência do redator em 4,7–5,1%, mas não tornou o loop especulativo completo mais rápido. Este resultado é específico da nossa carga de trabalho: nossa implantação do Qwen em lote na Blackwell utiliza decodificação especulativa sob condições diferentes.
Outros experimentos incluíram a redução de inicializações de GPU, a sobreposição de fases inteiras, o uso de blocos de preenchimento maiores, a aplicação de fusão mais ampla, a aceleração do roteador e a combinação da projeção de saída com a seleção de tokens. Nenhum deles melhorou o loop de inferência completo.
As medições dos limites de hardware também mostraram pouca margem remanescente nas principais operações de preenchimento e decodificação. As GEMMs e GEMVs de MoE atingiram 97,9% e 90,3% das taxas mais rápidas de leitura de peso sustentadas para seus padrões de acesso. A remoção da aritmética da GEMV esparsa alterou a taxa de transferência em apenas 0,2%, confirmando que as leituras de peso, e não a computação, eram o recurso limitante. A multiplicação de matrizes do preenchimento alcançou de forma semelhante 93% do limite teórico da matriz isoladamente e 80–86% dentro dos modelos testados.
Desempenho de ponta a ponta
A comparação de ponta a ponta carrega bytes de ponto de verificação de 4 bits idênticos em ambos os motores e executa uma solicitação por vez em um único M5 Max de 40 núcleos e 128 GB. Em cada rodada, os dois motores são executados em ordem alternada para reduzir o viés decorrente de carga em segundo plano e alterações na temperatura do chip. Comparamos com o caminho de geração direta mais rápido do MLX-LM, e não com seu servidor, de modo que a medição concentra-se na execução do modelo em vez da sobrecarga de atendimento.
A varredura abrange dez comprimentos de prompt para preenchimento e dez comprimentos de contexto para decodificação, de 256 a 128 mil tokens. A taxa de transferência de preenchimento primeiro aumenta à medida que o motor distribui custos fixos de configuração entre mais tokens. O preenchimento atinge o pico em torno de um prompt de 4 mil tokens e, em seguida, diminui porque as dez camadas de atenção completa realizam mais trabalho à medida que o prompt cresce. A decodificação permanece quase constante em contextos curtos e diminui assim que a leitura do cache de KV em crescimento se torna significativa. O motor personalizado é mais rápido em todos os comprimentos registrados.
Como a execução especializada pode alterar a ordem das operações de ponto flutuante, também verificamos a consistência numérica em relação ao MLX-LM. Em uma comparação forçada por professor, ambos os motores previram o próximo token a partir do mesmo prefixo de referência em cada uma das 192 posições, evitando que diferenças anterioresafetassem as entradas posteriores. A perplexidade do Lily foi apenas 0,04% maior, e ele selecionou o mesmo token melhor classificado em 96,35% das posições testadas.
Criado para a plataforma local
O Apple Silicon não é uma GPU de datacenter menor. É uma plataforma completa de inferência local com características próprias de hardware e software. A memória unificada oferece a um único nó um teto muito alto para a quantidade de modelo e estado que ele pode armazenar. Os Aceleradores Neurais M5 absorvem o trabalho de matriz densa no preenchimento. As unidades lógicas aritméticas (ALUs) de vetor lidam com o restante de baixo aproveitamento e limitado por largura de banda na decodificação.
O Qwen adiciona novas oportunidades de especialização: manter o roteamento de especialistas e o estado recorrente na GPU, eliminar intermediários desnecessários, sobrepor trabalhos independentes, reutilizar dados de KV compartilhados e adaptar os kernels à forma da carga de trabalho.
Com a otimização específica para o modelo e para a plataforma, um único Mac pode executar um modelo esparso grande com eficiência. Trabalhos futuros ampliarão a cobertura entre modelos, chips e cargas de trabalho de atendimento, transformando os mecanismos validados aqui em uma única configuração em uma política de tempo de execução mais geral.
O princípio mais amplo é adequar o motor tanto à arquitetura do modelo quanto aos caminhos específicos de computação e memória do hardware. Conforme os modelos de pesos abertos de fronteira e o hardware evoluem, a inferência local de alto desempenho dependerá cada vez mais de motores adaptados a ambos, em vez daqueles que abstraem suas diferenças.
Citação
@online{perplexity2026OptimizingOnDeviceInferenceForAppleSilicon,
author = {{Perplexity} and Yibo Wu and Lequn Chen and Kevin Hu and Phi Hoang and Claire Beamer and Jeremy Yang and Denis Yarats},
title = {{Optimizing on-device inference for Apple Silicon}},
date = {2026-09-01},
url = {https://www.perplexity.ai/hub/blog/optimizing-on-device-inference-for-apple-silicon}
}