Otimizando a inferência no dispositivo para o Apple Silicon
Um mecanismo local personalizado que melhora a taxa de transferência de preenchimento e decodificação.
Para que essa divisão de trabalho pareça perfeita, a inferência local deve acompanhar o restante da tarefa. Isso requer um mecanismo que possa processar prompts rapidamente e sustentar uma alta taxa de geração de tokens.
O Lily, nosso mecanismo de inferência local leve, foi criado especificamente para o Apple Silicon e o Qwen3.6-35B-A3B, com otimizações separadas para preenchimento e decodificação. O código-fonte do mecanismo será aberto em breve.
Introdução
Uma forma comum de executar LLMs em um Mac é com 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 gama de modelos de linguagem. Juntos, o MLX e o MLX-LM fornecem uma pilha pronta para uso e de uso geral para inferência de LLM local.
O Qwen3.6-35B-A3B é um modelo esparso e híbrido: ele utiliza roteamento por mistura de especialistas (MoE) e combina estados recorrentes de tamanho fixo com atenção completa. Essas escolhas arquiteturais reduzem a quantidade de computação necessária, mas também criam cargas de trabalho irregulares. Os tokens são roteados para diferentes pesos de especialistas, e os estados recorrentes têm natureza sequencial.
O MLX-LM já seleciona kernels otimizados para fases de inferência e formatos de carga de trabalho comuns, mas suas operações reutilizáveis devem dar suporte a muitas arquiteturas de modelos. Um mecanismo dedicado ao Qwen pode se especializar no nível do modelo e do runtime, 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 runtime 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 chat-completions 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 velocidade com que o mecanismo processa o prompt; a taxa de transferência de decodificação captura a velocidade com que ele gera tokens de saída.
Fazemos benchmarks do Qwen3.6-35B-A3B em um único MacBook Pro equipado com um M5 Max com uma GPU de 40 núcleos e 128 GB de memória unificada. Em dez comprimentos de prompt para preenchimento e dez comprimentos de contexto para decodificação, de 256 a 128 mil tokens (K = 1.024), o mecanismo atinge, em média, 1,23× a taxa de transferência de preenchimento do MLX-LM e 1,35× a sua taxa de transferência de decodificação. Com um prompt de 4 mil tokens e um contexto de decodificação de 4 mil tokens, o mecanismo personalizado alcança 5.749,9 tokens de preenchimento por segundo e 186,6 tokens de decodificação por segundo, em comparação com 4.737,5 e 140,9 do MLX-LM. Em uma sessão de vários turnos, essa economia de tempo se acumula a cada chamada adicional do modelo.

A seguir, explicamos como a arquitetura do Qwen cria oportunidades de otimização específicas para o 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 trazer retornos, antes de encerrar com uma comparação de ponta a ponta com o MLX-LM.
Oportunidades de otimização específicas para o Qwen no Apple Silicon
O Qwen cria três formatos de carga de trabalho distintos
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 irregular: os especialistas recebem números diferentes de tokens, e cada token requer 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 camada retêm informações anteriores de maneiras diferentes.
As camadas de atenção usam atenção de consulta agrupada (GQA). O Qwen tem 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 reter, 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 precedente. Durante o preenchimento, no entanto, um mecanismo 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 irregulares, 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 diferentes caminhos para diferentes cargas de trabalho
O preenchimento processa muitas 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 usados. O preenchimento pode reutilizar cada bloco de pesos em centenas ou milhares de linhas. A decodificação, em sua maior parte, não pode, uma vez que cada novo token requer outra passagem pelos pesos.
O Apple Silicon coloca a CPU e a GPU atrás da 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 de GPU separada, mas não torna a movimentação de dados gratuita. A leitura de pesos e valores intermediários ainda consome largura de banda de memória, enquanto os registradores e outros armazenamentos no chip são mais rápidos, mas muito menores.
A GPU do M5 também fornece diferentes caminhos de computação. As camadas lineares do preenchimento usam multiplicação geral de matriz-matriz (GEMM), aplicando uma matriz de pesos a muitas linhas de uma só vez. GEMMs compatíveis podem usar o Acelerador Neural em cada núcleo de GPU por meio de operações de tensor do Metal 4. A decodificação de lote 1, em vez disso, usa multiplicação geral de matriz-vetor (GEMV), aplicando os mesmos pesos a uma linha. Com pouca reutilização de pesos, o GEMV é limitado principalmente pela largura de banda da memória e é mais adequado para as unidades lógicas aritméticas (ALUs) vetoriais da GPU do que para Aceleradores Neurais projetados para operações de matriz 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 usa atenção ciente de GQA. Esses recursos são o ponto de partida compartilhado para a inferência eficiente do Qwen no Apple Silicon.
Estratégia de otimização
O escopo mais restrito do Lily permite que ele coordene esses caminhos de execução compartilhados em torno da arquitetura e das dimensões exatas do Qwen. Ele usa 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. Usar execução orientada a matrizes quando o preenchimento puder reutilizar pesos em muitas linhas e execução orientada a vetores quando a decodificação de lote 1 processar uma linha de cada vez.
- Mapear a estrutura do Qwen para a GPU minimizando a movimentação de dados. Manter os pesos compactados até que sejam usados, 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 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 mecanismos idênticas em todo o resto que diferem apenas na otimização em estudo. Como esses experimentos comparam versões do nosso mecanismo 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 roteia essas linhas de forma irregular 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 de especialistas esparsos em torno das linhas roteadas, manter a varredura do Gated DeltaNet no chip e dividir prompts longos em trechos limitados.

Otimizar a computação de especialistas esparsos
Dequantizar pesos durante a multiplicação de matrizes
O ponto de verificação do Qwen3.6-35B-A3B usa quantização afim baseada em grupos de 4 bits. 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 cerca de 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 usada para a multiplicação de matrizes consome operandos bfloat16 em vez da representação compactada de 4 bits. Antes da multiplicação, a GPU deve reconstruir os pesos em bfloat16. O GEMM agrupado otimizado 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 usa 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 o GEMM agrupado 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
O GEMM agrupado 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 enviadas para cada especialista. Uma varredura de prefixo transforma essas contagens em deslocamentos iniciais, uma etapa de dispersão coloca as linhas em seus grupos de especialistas e um mapa de blocos lista os blocos de matriz de tamanho fixo que o GEMM agrupado 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. Uma ablação, em vez disso, 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 mostra por que a contagem de kernels isoladamente pode ser enganosa: a rota mais rápida inicia mais kernels, mas nunca espera pela CPU dentro da camada.
Ajustar o tamanho do bloco à carga de especialistas
Com um prompt de 2 mil tokens, o roteamento de cada token para oito dos 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.
O GEMM agrupado 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 em 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 são, portanto, acoplados.
Uma ablação fixa o bloco em 16 linhas. Em comparação com esse controle, habilitar o bloco de 32 linhas com quatro simdgroups melhorou o preenchimento de ponta a ponta em 13,2% em 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 registrador desativada, a ablação usa uma varredura baseada em blocos. Com um prompt de 2 mil tokens, esse caminho move 256 MiB (mebibibytes) de estado por camada e para repetidamente os tópicos cooperativos em barreiras (pontos de sincronização em que todos os tópicos participantes devem esperar 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 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 somente após a varredura.
O estado e seu portão usam 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 registrador melhorou o preenchimento de ponta a ponta em 5,6%. Os 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 runtime processa um prompt longo como uma sequência de trechos limitados, 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ária 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 apenas os valores temporários de um segmento ativos de cada vez, liberando ou reutilizando esse armazenamento antes de processar o segmento seguinte. Isso limita o pico de memória de trabalho e permite que o mecanismo processe prompts mais longos sem alterar a saída do modelo.
O preenchimento em trechos é popular em muitos mecanismos e é crucial para atender a longas trajetórias de vários turnos nestes ambientes com restrição de memória. O tempo total de preenchimento para as camadas de atenção permanece quadrático em relação ao comprimento do prompt, com alguma sobrecarga adicional devido a cargas de KV repetidas de trechos anteriores.
Decodificação: minimizar os bytes movidos por token
A decodificação de 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 mecanismo move para cada token. As alterações de 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 trabalho de linha única para kernels especializados de matriz-vetor. Como o Lily não usa o MLX, o runtime personalizado deve fornecer a mesma estratégia básica. Nosso GEMV paralelo por linha foi projetado 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 runtime, em vez disso, 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 o trabalho independente da GPU
Em uma etapa de decodificação de lote 1 registrada, a geração de um token iniciou 795 kernels de GPU. Suas dependências formaram 555 estágios sequenciais, deixando alguns kernels livres para serem executados simultaneamente. O modo de execução serial do Metal, no entanto, executou cada kernel em ordem.
O caminho de decodificação otimizado registra as dependências reais de dados em uma passagem concorrente do Metal. Inicializações de kernel independentes podem ser executadas ao mesmo tempo quando os recursos da GPU permitirem. Uma barreira é inserida apenas quando um trabalho posterior requer um resultado anterior.
Reduzir o tráfego intermediário e de estado
Kernels separados geralmente 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 de especialistas com sua pontuação de roteamento e o resultado do especialista compartilhado; a preparação de consultas e chaves 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ências: quando uma gravação intermediária desaparece, o mesmo acontece com a barreira que protegia seu consumidor.
Ler 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, os 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 cargas coalescentes faz com que os 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 chaves de 33,8 para 47,9 GB/s, aumentou a largura de banda de valores 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, realiza a mesma aritmética e produz bytes de saída idênticos, ao mesmo tempo em que reduz oito solicitações de KV independentes a duas cargas compartilhadas. 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 vale a pena 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 runtime mantém o caminho de atenção geral abaixo de 32 mil tokens e usa o caminho de bloco fixo em 32 mil ou mais. A alternância se aplica quando cada cabeça tem 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 alternância e usa sempre o caminho geral. A ativação da rota de bloco fixo melhorou a decodificação de ponta a ponta em 7,7% a 32 mil, 27,4% a 64 mil e 40,2% a 128 mil.
Limites de otimização adicional
Algumas alterações melhoraram uma operação isolada, mas não melhoraram a inferência de ponta a ponta.
A decodificação especulativa, que usa um modelo menor para propor tokens para o modelo completo verificar, tornou a decodificação de 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 peso de especialistas lidos. A redução do vocabulário de saída do gerador melhorou a taxa de transferência do gerador em 4,7–5,1%, mas não tornou o loop especulativo completo mais rápido. Este resultado é específico da carga de trabalho: nossa implantação do Qwen em lote no Blackwell usa 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. Os GEMMs e GEMVs de MoE atingiram 97,9% e 90,3% das taxas de leitura de peso sustentadas mais rápidas para seus padrões de acesso. A remoção da aritmética do GEMV esparso 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 de preenchimento atingiu de forma semelhante 93% do limite teórico de matrizes 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 mecanismos e executa uma solicitação por vez em um único M5 Max de 40 núcleos e 128 GB. Dentro de cada rodada, os dois mecanismos são executados em ordem alternada para reduzir o viés 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 o seu servidor, de modo que a medição se concentra na execução do modelo e não na 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 aumenta inicialmente à medida que o mecanismo distribui os 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, cai 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 mecanismo 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 mecanismos previram o próximo token a partir do mesmo prefixo de referência em cada uma das 192 posições, impedindo que diferenças anterioresafetassem entradas posteriores. A perplexidade do Lily foi apenas 0,04% maior, e ele selecionou o mesmo token mais bem classificado em 96,35% das posições testadas.

Criado para a plataforma local
O Apple Silicon não é uma GPU de data center menor. É uma plataforma de inferência local completa com suas próprias características de hardware e software. A memória unificada dá a um único nó um limite muito alto sobre a quantidade de modelo e estado que ele pode conter. Os Aceleradores Neurais do M5 absorvem o trabalho de matriz densa no preenchimento. As ALU vetoriais lidam com o restante vinculado à largura de banda e de baixa reutilização na decodificação.
O Qwen adiciona mais oportunidades de especialização: manter o roteamento de especialistas e o estado recorrente na GPU, eliminar intermediários desnecessários, sobrepor trabalho independente, reutilizar dados de KV compartilhados e adaptar kernels à forma da carga de trabalho.
Com a otimização específica para o modelo e a plataforma, um único Mac pode executar um grande modelo esparso de forma eficiente. O trabalho futuro ampliará a cobertura entre modelos, chips e cargas de trabalho de atendimento, e transformará os mecanismos validados aqui em uma configuração em uma política de runtime mais geral.
O princípio mais amplo é adequar o mecanismo tanto à arquitetura do modelo quanto aos caminhos específicos de computação e memória do hardware. À medida que os modelos de pesos abertos de ponta e o hardware evoluem, a inferência local de alto desempenho dependerá cada vez mais de mecanismos adaptados a ambos, em vez de mecanismos que abstraem suas diferenças.