Optimización da inferencia no dispositivo para Apple Silicon

Un motor local personalizado que mellora o rendemento de preenchido e descodificación.

AutoresPerplexity Engineering

A computación híbrida en Apple silicon orquestra unha tarefa entre a intelixencia de vangarda na nube e un modelo local no Mac. Os modelos na nube xestionan a investigación e o razoamento, mentres que un modelo local traballa con ficheiros e aplicacións privadas no Mac.

Para que esta división do traballo se sinta fluída, a inferencia local debe manter o ritmo co resto da tarefa. Iso require un motor que poida procesar avisos rapidamente e soster unha alta taxa de xeración de tokens.

Lily, o noso motor de inferencia local lixeiro, está deseñado especificamente para Apple silicon e Qwen3.6-35B-A3B, con optimizacións separadas para o preenchido e a descodificación. O motor abrirá o seu código fonte proximamente.

Introdución

Un xeito habitual de executar LLMs nun Mac é con MLX, o marco de aprendizaxe automática de código aberto de Apple para Apple silicon. A súa biblioteca compañeira, MLX-LM, engade os compoñentes necesarios para cargar e xerar texto cunha ampla gama de modelos de linguaxe. Xuntos, MLX e MLX-LM proporcionan unha pila lista para usar e de uso xeral para a inferencia local de LLM.

Qwen3.6-35B-A3B é un modelo híbrido e disperso: emprega enrutamento de adestramento de expertos (MoE) e combina estados recorrentes de tamaño fixo con atención plena. Estas eleccións arquitectónicas reducen a cantidade de computación requirida, mais tamén crean cargas de traballo irregulares. Os tokens diríxense a diferentes pesos de expertos e os estados recorrentes son de natureza secuencial.

MLX-LM xa selecciona núcleos optimizados para as fases de inferencia e formas de carga de traballo comúns, mais as súas operacións reutilizables deben admitir moitas arquitecturas de modelos. Un motor dedicado a Qwen pode especializarse a nivel de modelo e de tempo de execución, coordinando núcleos, movemento de datos e planificación arredor da estrutura fixa do modelo.

Lily implementa esta especialización de extremo a extremo nun único proceso. Un tempo de execución de Rust carga o punto de control do modelo e xestiona o estado da sesión e o bucle de xeración, unha API de chat de completado compatible con OpenAI acepta solicitudes e transmite tokens, e os núcleos de Metal personalizados executan operacións específicas de Qwen. Nin PyTorch nin MLX están na ruta de execución.

Onde se sitúan a xeneralidade e a especialización nas dúas pilas de inferencia. MLX-LM describe o modelo como operacións de matriz MLX compostas, que MLX programa a través de núcleos reutilizables. En cambio, Lily sitúa a estrutura do modelo, os plans de execución específicos de fase e a selección de núcleos nun único tempo de execución en Rust construído arredor de Qwen e silicio de Apple.
Onde se sitúan a xeneralidade e a especialización nas dúas pilas de inferencia. MLX-LM describe o modelo como operacións de matriz MLX compostas, que MLX programa a través de núcleos reutilizables. Pola contra, Lily sitúa a estrutura do modelo, os plans de execución específicos de cada fase e a selección de núcleos nun único tempo de execución de Rust construído arredor de Qwen e Apple silicon.

Medimos o rendemento de preenchido e de descodificación por separado. O rendemento de preenchido recolle a rapidez coa que o motor procesa o aviso; o rendemento de descodificación recolle a rapidez coa que xera os tokens de saída.

Comparamos Qwen3.6-35B-A3B nun único MacBook Pro equipado cun chip M5 Max con GPU de 40 núcleos e 128 GB de memoria unificada. En dez lonxitudes de aviso para o preenchido e dez lonxitudes de contexto para a descodificación, desde 256 ata 128K tokens (K = 1024), o motor ofrece de media 1,23× o rendemento de preenchido de MLX-LM e 1,35× o seu rendemento de descodificación. Cunha solicitude de 4K tokens e un contexto de descodificación de 4K tokens, o motor personalizado atinxe 5749,9 tokens de preenchido por segundo e 186,6 tokens de descodificación por segundo, en comparación cos 4737,5 e 140,9 de MLX-LM. Nunha sesión de varias quendas, estes aforros de tempo acumulanse con cada chamada adicional ao modelo.

Rendimento medio aritmético en dez lonxitudes igualmente ponderadas de 256 a 128K tokens. Lily alcanza unha media de 4.156 tokens de preenchimento/s fronte aos 3.388 de MLX-LM (1,23×), e 170,0 tokens de descodificación/s fronte a 126,4 (1,35×). O preenchimento varía a lonxitude do aviso; a descodificación varía a lonxitude do contexto.
Rendemento medio aritmético en dez lonxitudes igualmente ponderadas de 256 a 128K tokens. Lily acadou unha media de 4156 tokens de preenchido/s fronte aos 3388 de MLX-LM (1,23×), e 170,0 tokens de descodificación/s fronte aos 126,4 (1,35×). O preenchido varía a lonxitude do aviso; a descodificación varía a lonxitude do contexto.

A continuación, explicamos como a arquitectura de Qwen crea oportunidades de optimización específicas do modelo en Apple silicon. Despois, repasamos os cambios resultantes no preenchido e na descodificación. Tamén tratamos onde a optimización adicional deixa de ser rentable antes de concluír cunha comparación de extremo a extremo con MLX-LM.

Oportunidades de optimización específicas de Qwen en Apple silicon

Qwen crea tres formas de carga de traballo distintas

Qwen3.6-35B-A3B contén 35 mil millóns de parámetros mais activa só uns 3 mil millóns para cada token. Un enrutador pontúa 256 subredes de expertos e selecciona oito, xunto cun experto compartido que procesa cada token. Este deseño de MoE disperso reduce a computación mais produce traballo desequilibrado: os expertos reciben diferentes números de tokens e cada token require pesos dunha combinación diferente de expertos.

Qwen tamén combina 10 capas de atención plena con 30 capas de Gated DeltaNet. Estes dous tipos de capas retienen a información anterior de diferentes xeitos.

As capas de atención empregan a atención de consultas agrupadas (GQA). Qwen ten 16 cabeceiras de consulta e dúas cabeceiras de clave-valor (KV), con oito cabeceiras de consulta compartindo cada cabeceira KV. Compartir fai que a caché KV sexa máis pequena e permite que os datos almacenados na caché se reutilicen entre as cabeceiras de consulta. A caché aínda almacena novas claves e valores para cada token, polo que cada paso de descodificación le máis datos a medida que o contexto medra.

Pola contra, Gated DeltaNet comprime a información anterior nun estado recorrente de tamaño fixo. Unha compuerta aprendida controla canto do estado existente se debe conservar, mentres que unha actualización delta incorpora información do token actual. O modelo define estas actualizacións de forma recorrente, polo que cada token depende do estado producido polo token precedente. Durante o preenchido, con todo, un motor pode avaliar o mesmo cálculo de dúas maneiras. Pode explorar os tokens directamente mentres transporta o estado cara a adiante, ou reorganizar as actualizacións en bloques que expoñen máis operacións de matrices e paralelismo a nivel de token. Que enfoque sexa máis rápido depende das dimensións do modelo, da carga de traballo e do hardware.

Xuntas, estas estruturas crean tres patróns computacionais: grupos de expertos desiguais, atención sobre unha caché en crecemento e unha recorrencia de tamaño fixo que se pode avaliar directamente ou en bloques.

Apple silicon ofrece diferentes rutas para diferentes cargas de traballo

O preenchido procesa moitas filas de activación de tokens de aviso á vez. A carga de traballo local considerada aquí normalmente descodifica unha solicitude á vez (lote 1) e procesa unha nova fila por paso. Esta diferenza cambia como se empregan os mesmos pesos do modelo. O preenchido pode reutilizar cada bloque de pesos en centos ou miles de filas. A descodificación non pode facelo na súa maioría, xa que cada novo token require outra pasada polos pesos.

Apple silicon sitúa a CPU e a GPU detrás da memoria unificada, un único fondo de memoria física accesible para ambas. Isto permite que o modelo permaneza residente sen manter unha copia de GPU separada, mais non fai que o movemento de datos sexa gratuíto. Ler pesos e valores intermedios aínda consume ancho de banda da memoria, mentres que os rexistros e outro almacenamento en chip son máis rápidos mais moito máis pequenos.

A GPU M5 tamén ofrece diferentes rutas de computación. As capas lineares do preenchido empregan a multiplicación xeral de matriz-matriz (GEMM), aplicando unha matriz de pesos a moitas filas á vez. Os GEMM compatibles poden empregar o acelerador neuronal en cada núcleo de GPU a través de operacións de tensores de Metal 4. No seu lugar, a descodificación de lote 1 emprega a multiplicación xeral de matriz-vector (GEMV), aplicando os mesmos pesos a unha fila. Con pouca reutilización de pesos, o GEMV está limitado principalmente polo ancho de banda da memoria e adecúase mellor ás unidades lóxicas aritméticas (ALU) vectoriais da GPU que aos aceleradores neuronais deseñados para operacións de matrices cunha maior reutilización de datos.

Estas rutas de execución non son exclusivas de Lily. MLX opera sobre a mesma memoria unificada e selecciona núcleos de matriz e vector optimizados segundo a forma da carga de traballo. A implementación de Qwen de MLX-LM xa agrupa o traballo de expertos, avalía Gated DeltaNet cun núcleo Metal recorrente fusionado e emprega atención consciente de GQA. Estas capacidades son o punto de partida compartido para unha inferencia eficiente de Qwen en Apple silicon.

Estratexia de optimización

O alcance máis estreito de Lily permítelle coordinar estas rutas de execución compartidas arredor da arquitectura e dimensións exactas de Qwen. Emprega rutas de GPU específicas para cada fase, mapea as cargas de traballo de expertos, recorrentes e de atención de Qwen para minimizar o movemento de datos, e selecciona núcleos e disposicións a partir da forma da carga de traballo medida. A estratexia consta de tres partes:

  1. Adaptar a ruta da GPU á fase de inferencia. Empregar execución orientada a matrices cando o preenchido poida reutilizar os pesos en moitas filas, e execución orientada a vectores cando a descodificación de lote 1 procesa unha fila á vez.
  2. Mapear a estrutura de Qwen na GPU minimizando o movemento de datos. Manter os pesos compresos ata que se empreguen, organizar o traballo de expertos enrutados sen volver á CPU, reter o estado de Gated DeltaNet en chip a través da súa exploración recorrente, e reutilizar os datos KV compartidos pola atención de consultas agrupadas.
  3. Adaptar os núcleos á forma da carga de traballo. Dentro de cada fase, seleccionar os tamaños de tellas, as disposicións de execución e as rutas de atención a partir do recuento de filas dispoñible, a distribución das filas entre os expertos, as dimensións da operación e a lonxitude actual do contexto.

As seguintes seccións explican estas eleccións. Para as optimizacións avaliadas en ablacións empareladas nun M5 Max, estimamos os seus efectos comparando configuracións de motores por outro lado idénticas que só se diferencian na optimización obxecto de estudo. Como estes experimentos comparan versións do noso motor consigo mesmas, explican mecanismos en vez de desglosar os resultados finais fronte a MLX-LM.

Preenchido: reutilizar os pesos e manter o enrutamento na GPU

O preenchido expone moitas filas de tokens á vez, mais Qwen enruta esas filas de xeito desequilibrado entre os expertos e anova o estado recorrente a través da secuencia. As súas optimizacións divídense en tres grupos: organizar o traballo de expertos dispersos arredor das filas enrutadas, manter a exploración de Gated DeltaNet en chip, e dividir os avisos longos en fragmentos acoutados.

Execución e residencia de datos para un fragmento de preenchimento delimitado a través dunha capa Qwen. A atención amplía a caché KV, mentres que Gated DeltaNet leva o seu estado recorrente de traballo en rexistros. Os metadatos de enrutamento de expertos permanecen na GPU, os pesos Q4 mantéñense empaquetados ata que se des cuantifican dentro do GEMM agrupado, e as activacións temporais limítanse ao fragmento actual.
Execución e residencia de datos para un fragmento de preenchido acoutado a través dunha capa de Qwen. A atención estende a caché KV, mentres que Gated DeltaNet transporta o seu estado recorrente de traballo en rexistros. Os metadatos de enrutamento de expertos permanecen na GPU, os pesos Q4 mantéñense empaquetados ata que se descuantifican dentro do GEMM agrupar, e as activacións temporais limítense ao fragmento actual.

Optimizar a computación de expertos dispersos

Descuantificar os pesos durante a multiplicación de matrices

O punto de control Qwen3.6-35B-A3B emprega cuantificación afín de 4 bits por grupos. Cada peso almacénase como un código enteiro de 4 bits, mentres que cada grupo de 64 pesos comparte unha escala e un sesgo bfloat16 empregados para reconstruír os seus valores. Isto reduce o modelo de 35 mil millóns de parámetros de aproximadamente 70 GB de pesos bfloat16 a un punto de control de 19,4 GB, o que fai viable manter o modelo residente no Mac.

A operación de tensores de Metal 4 empregada para a multiplicación de matrices consume operandos bfloat16 en lugar da representación de 4 bits empaquetada. Antes da multiplicación, a GPU debe reconstruír os pesos en bfloat16. O GEMM agrupar optimizado en Lily realiza esta conversión dunha pequena tella de peso á vez e mantén o resultado na memoria de grupos de fíos en chip durante o tempo suficiente para multiplicalo polas filas de activación enrutadas. A acumulación emprega punto flotante de 32 bits, e a saída escríbese en bfloat16. A matriz de pesos expandida completa nunca se crea na memoria unificada.

Na ablación, a descuantificación execútase como unha operación separada: expande os pesos de 4 bits nunha matriz bfloat16 na memoria unificada, despois da cal o núcleo de matriz le esa matriz de novo. Cun aviso de 512 tokens, mover a descuantificación ao GEMM agrupar incrementou o rendemento de preenchido de extremo a extremo nun 77,4 % ao eliminar esta escritura e lectura intermedias.

Manter o enrutamento de expertos na GPU

O GEMM agrupar necesita que as filas de activación asignadas a cada experto se almacenen xuntas. Despois de seleccionar oito expertos por token, un histograma conta cantas asignacións foron para cada experto. Unha exploración de prefixos converte eses contados en desprazamentos de inicio, un paso de dispersión coloca as filas nos seus grupos de expertos, e un mapa de bloques lista os bloques de matrices de tamaño fixo que o GEMM agrupar debe procesar.

A ruta optimizada mantén toda esta secuencia nun único búfer de comandos, un lote ordenado de operacións de GPU, para cada fragmento de aviso. Unha ablación fai unha pausa no seu lugar para que a CPU poida inspeccionar os intermedios de enrutamento e enviar a seguinte operación. Manter o histograma e a exploración de prefixos na GPU engade dous núcleos mais elimina a sincronización CPU-GPU dentro de cada capa de MoE.

Cun aviso de 512 tokens, activar o enrutamento residente na GPU incrementou o preenchido de extremo a extremo nun 89 %. Isto tamén mostra por que a cantidade de núcleos por si só pode ser enganosa: a ruta máis rápida lanza máis núcleos mais nunca agarda pola CPU dentro da capa.

Facer coincidir o tamaño da tella coa carga de expertos

Cun aviso de 2K tokens, enrutar cada token a oito de 256 expertos produce 16 384 asignacións de token-experto, ou unha media de 64 filas de activación por experto. A distribución real é desequilibrada: algúns expertos reciben moitas filas, mentres que outros reciben poucas.

O GEMM agrupar divide a saída de cada experto en tellas, que son pequenos bloques rectangulares da saída dunha multiplicación de matrices. Cada tella asígnase a un grupo de fíos de GPU. Nas GPU de Apple silicon, un grupo de fíos contén un ou máis grupos simd, cada un dos cales consta de 32 fíos que executan instrucións en paso sincronizado.

As tellas máis grandes reparten o custo de configuración entre máis filas e expoñen máis traballo en paralelo, mais unha parte dunha tella grande permanece inactiva cando un experto recibe só unhas poucas filas. O tamaño da tella e a cantidade de grupos simd están, polo tanto, acoplados.

Unha ablación fixa a tella en 16 filas. Fronte a ese control, activar a tella de 32 filas con catro grupos simd mellorou o preenchido de extremo a extremo nun 13,2 % a 2K tokens.

Manter o estado recorrente en chip

Durante o preenchido, cada capa de Gated DeltaNet explora o aviso en orde mentres transporta o seu estado recorrente cara a adiante. Coa residencia en rexistros desactivada, a ablación emprega unha exploración por bloques. Cun aviso de 2K tokens, esa ruta move 256 MiB (mebibytes) de estado por capa e detén repetidamente os fíos que cooperan en barreiras, puntos de sincronización onde todos os fíos participantes deben agardar uns polos outros.

O estado recorrente é unha matriz. O núcleo optimizado asigna cada columna a un grupo simd. O grupo simd divide a columna entre os seus fíos, carga a columna nos seus rexistros unha soa vez e mantén o estado durante toda a exploración. Os fíos intercambian resultados intermedios mediante operacións de grupos simd en lugar de memoria de grupos de fíos, un almacenamento en chip compartido nun grupo de fíos. O estado completado escríbese de novo só despois da exploración.

O estado e a súa porta empregan un formato de punto flotante de 32 bits porque os pequenos erros de redondeo acumúlanse nas actualizacións secuenciais. As activacións de consultas e claves permanecen en bfloat16.

Cun aviso de 2K tokens, activar a exploración residente en rexistros mellorou o preenchido de extremo a extremo nun 5,6 %. Os GEMM de expertos representaron preto do 90 % do tempo de preenchido. A exploración secuencial non expón suficiente traballo de matriz reutilizable como para beneficiarse dos aceleradores neuronais.

Acoutar a memoria temporal coa fragmentación de avisos

O tempo de execución procesa un aviso longo como unha secuencia de fragmentos acoutados en vez de manter datos temporais para cada token de aviso na memoria á vez. Os pesos do modelo permanecen residentes na memoria unificada, mentres que o estado recorrente e a caché KV transportan o contexto dun fragmento ao seguinte. Non se descarta ningún contexto anterior.

Sen a fragmentación, as matrices de activación temporal medran co aviso completo e compiten cos pesos do modelo, o estado recorrente e a caché KV pola memoria unificada. A fragmentación mantén activos os valores temporais dun só segmento á vez, e logo libera ou reutiliza ese almacenamento antes de procesar o seguinte segmento. Isto limita a memoria de traballo máxima e permite ao motor procesar avisos máis longos sen cambiar a saída do modelo.

O preenchido fragmentado é popular en moitos motores e é crucial para servir traxectorias longas de varias quendas nestes entornas con limitacións de memoria. O tempo total de preenchido para as capas de atención permanece cuadrático respecto á lonxitude do aviso, con algúns gastos xerais engadidos polas cargas KV repetidas de fragmentos anteriores.

Descodificación: minimizar os bytes movidos por token

A descodificación de lote 1 procesa unha nova fila á vez. Con pouca reutilización de pesos, o seu rendemento depende principalmente de cantos bytes move o motor para cada token. Os cambios de descodificación divídense en catro grupos: optimizar a ruta de peso dunha soa fila, manter cada paso na GPU, reducir o tráfico intermedio e de estado, e ler a caché de atención de forma eficiente.

Fluxo de datos para un paso de descodificación en lote 1 e dous mecanismos que reducen o tempo de inactividade e o tráfico na caché. (A) A GPU transmite os pesos Q4 e o estado do modelo a través da atención, Gated DeltaNet, enrutamento e núcleos de expertos fusionados, e logo escribe o token seleccionado directamente na ranura de entrada do seguinte paso mentres envía unha copia á CPU. (B) A programación consciente de dependencias permite que os núcleos independientes se solapen. (C) O empaquetado GQA permite que catro cabezas de consulta compartan cada carga de filas KV, o que reduce oito solicitudes independentes a dúas cargas compartidas.
Fluxo de datos para un paso de descodificación de lote 1 e dous mecanismos que reducen o tempo de inactividade e o tráfico na caché. (A) A GPU transmite os pesos Q4 e o estado do modelo a través da atención, Gated DeltaNet, o enrutamento e os núcleos de expertos fusionados, e logo escribe o token seleccionado directamente na ranura de entrada do seguinte paso mentres envía unha copia á CPU. (B) A planificación consciente de dependencias permite que os núcleos independentes se superpoongan. (C) O empaquetado GQA permite que catro cabeceiras de consulta compartan cada carga de filas KV, reducindo oito solicitudes independentes a dúas cargas compartidas.

Optimizar a ruta de peso dunha soa fila

MLX xa despacha traballo dunha soa fila a núcleos especializados de matriz-vector. Como Lily non emprega MLX, o tempo de execución personalizado debe proporcionar a mesma estratexia básica. O noso GEMV paralelo por filas está deseñado para unha fila de activación. Un grupo simd coopera na saída mentres le diferentes partes da matriz de pesos en paralelo.

Manter cada paso de descodificación na GPU

Manter a transferencia de tokens na GPU

Cada paso de descodificación remata seleccionando o seguinte token; o seguinte paso comeza con ese token como entrada. Enviar a selección á CPU e logo de volta á GPU engade un punto de sincronización a cada token. Pola contra, o noso tempo de execución alterna entre dous búferes de comandos e dúas ranuras de tokens residentes na GPU. A GPU selecciona o token coa puntuación máis alta e escribe o seu ID de token directamente na ranura de entrada para o seguinte paso de descodificación, mentres a CPU prepara o traballo posterior.

Superpoñer traballo de GPU independente

Nun paso de descodificación de lote 1 rexistrado, a xeración dun token lanzou 795 núcleos de GPU. As súas dependencias formaron 555 etapas secuenciais, o que deixou algúns núcleos libres para executarse concorrentemente. Con todo, o modo de execución serial de Metal executou cada núcleo en orde.

A ruta de descodificación optimizada rexistra as dependencias de datos reais nunha pasada de Metal concorrente. Os lanzamentos de núcleos independentes poden executarse ao mesmo tempo cando os recursos da GPU o permiten. Insírese unha barreira só cando un traballo posterior require un resultado anterior.

Reducir o tráfico intermedio e de estado

Os núcleos separados adoitan materializar un intermedio: un núcleo escribe un resultado temporal na memoria, e o seguinte le o resultado de novo. A ruta de descodificación optimizada fusiona catro cadeas: as dúas proxeccións de entrada de expertos coa súa activación con compuertas; a proxección de saída de expertos coa súa puntuación de enrutamento e o resultado do experto compartido; a preparación de consultas e claves antes da atención; e a actualización recorrente coa súa normalización. Cada núcleo fusionado mantén os valores temporais nos rexistros en lugar de envialos a través da memoria.

A fusión tamén abrevia o grafo de dependencias: cando desaparece unha escritura intermedia, tamén o fai a barreira que protexía o seu consumidor.

Ler a caché de atención de forma eficiente

Coalescer as lecturas da caché de atención

A atención le chaves e valores da caché KV durante cada paso de descodificación. Na ablación, os fíos de GPU veciños non sempre solicitan bytes veciños, o que forza ao sistema de memoria a servir máis transaccións separadas. Activar cargas coalescentes fai que os fíos adxacentes soliciten bytes adxacentes para que o hardware poida combinar as súas lecturas.

Na configuración bfloat16, a coalescencia incrementou o ancho de banda de claves de 33,8 a 47,9 GB/s, incrementou o ancho de banda de valores de 42,0 a 61,8 GB/s, e mellorou a descodificación de extremo a extremo nun 2,1 % cun contexto de 3840 tokens.

Empaquetar as cabeceiras de consulta para reutilizar as filas KV

A atención de consultas agrupadas permite que oito cabeceiras de consulta compartan unha cabeceira KV. Na ablación, cada cabeceira de consulta execútese nun grupo simd independente, polo que as oito solicitan de forma independente a mesma fila KV na caché. O núcleo optimizado empaqueta catro cabeceiras de consulta nun grupo de fíos, que carga cada fila KV unha soa vez e a reutiliza en catro cálculos de atención. Un segundo grupo de fíos xestiona as catro cabeceiras restantes.

Esta técnica, comunmente chamada empaquetado GQA, realiza a mesma aritmética e produce bytes de saída idénticos ao tempo que reduce oito solicitudes KV independentes a dúas cargas compartidas. Fronte á ablación sen empaquetar, mellorou o rendemento de descodificación de extremo a extremo nun 23,8 % cun contexto de 32K tokens.

Cambiar as disposicións de atención en contextos longos

Cada paso de descodificación nunha capa de atención plena examina a caché KV existente. Un disposición de bloques fixos divide esa caché en pezas iguais que a GPU pode procesar en paralelo. A súa planificación adicional non compensa cando a caché é pequena, mais a disposición de bloques fixos equilibra o traballo de maneira máis uniforme a medida que medra o contexto.

Para este modelo, o tempo de execución mantén a ruta de atención xeral por abaixo dos 32K tokens e emprega a ruta de bloques fixos a 32K ou máis. O cambio aplícase cando cada cabeceira ten 256 valores e oito cabeceiras de consulta comparten unha cabeceira KV; outras formas permanecen na ruta xeral. Unha ablación desactiva este cambio e emprega sempre a ruta xeral. Activar a ruta de bloques fixos mellorou a descodificación de extremo a extremo nun 7,7 % a 32K, un 27,4 % a 64K e un 40,2 % a 128K.

Límites dunha futura optimización

Algúns cambios melloraron unha operación illada mais non melloraron a inferencia de extremo a extremo.

A descodificación especulativa, que emprega un modelo máis pequeno para propoñer tokens para que o modelo completo os verifique, fixo que a descodificación de lote 1 fose un 18 % máis lenta. A verificación procesou grupos de dúas a cinco filas, unha forma ineficaz para este hardware, e as filas a miúdo seleccionaron diferentes expertos, o que incrementou a cantidade de datos de pesos de expertos lidos. Reducir o vocabulario de saída do redactor mellorou o rendemento do redactor nun 4,7–5,1 %, mais non fixo que o bucle especulativo completo fose máis rápido. Este resultado é específico da carga de traballo: a nosa implementación de Qwen en lotes en Blackwell emprega a descodificación especulativa baixo diferentes condicións.

Outros experimentos incluíron reducir os lanzamentos de GPU, superpoñer fases enteiras, empregar tellas de preenchido máis grandes, aplicar unha fusión máis ampla, acelerar o enrutador e combinar a proxección de saída coa selección de tokens. Ningún mellorou o bucle de inferencia completo.

As medicións dos límites do hardware tamén mostraron pouca marxe restante nas operacións principais de preenchido e descodificación. Os GEMM e GEMV de MoE acadaron o 97,9 % e o 90,3 % das taxas de lectura de pesos sostidas máis rápidas para os seus patróns de acceso. Eliminar a aritmética do GEMV disperso cambiou o rendemento nun 0,2 %, o que confirma que as lecturas de pesos, máis ca a computación, eran o recurso limitante. A multiplicación de matrices do preenchido acadou de maneira similar o 93 % do límite teórico de matrices de forma illada e o 80–86 % dentro dos modelos probados.

Rendemento de extremo a extremo

A comparación de extremo a extremo carga bytes de puntos de control de 4 bits idénticos en ambos os motores e executa unha solicitude á vez nun M5 Max de 40 núcleos e 128 GB. Dentro de cada rolda, os dous motores executanse en orde alternativa para reducir o sesgo da carga de fondo e os cambios na temperatura do chip. Comparamos coa ruta de xeración directa máis rápida de MLX-LM, non co seu servidor, polo que a medición céntrase na execución do modelo en vez de nos gastos xerais de servizo.

O barrido abarca dez lonxitudes de aviso para o preenchido e dez lonxitudes de contexto para a descodificación, desde 256 ata 128K tokens. O rendemento de preenchido primeiro sube a medida que o motor reparte os custos de configuración fixos entre máis tokens. O preenchido atinxe o seu máximo arredor dun aviso de 4K tokens, e logo baixaba porque as dez capas de atención plena realizan máis traballo a medida que o aviso medra. A descodificación permanece case plana en contextos curtos e declina unha vez que a lectura da caché KV en crecemento se torna significativa. O motor personalizado é máis rápido en cada lonxitude rexistrada.

Dado que a execución especializada pode cambiar a orde das operacións en punto flotante, tamén comprobamos a consistencia numérica con MLX-LM. Nunha comparación forzada polo profesor, ambos os motores prediciron o seguinte token a partir do mesmo prefixo de referencia en cada unha das 192 posicións, evitando que as diferenzas anteriores afectasen as entradas posteriores. A perplejidade de Lily foi só un 0,04 % superior e seleccionou o mesmo token mellor valorado no 96,35 % das posicións probadas.

Rendimento de preenchimento por lonxitude de aviso e rendemento de descodificación por lonxitude de contexto para Qwen3.6-35B-A3B Q4, lote 1, nun M5 Max de 40 núcleos e 128 GB. En dez lonxitudes de 256 a 128K tokens, Lily é máis rápido en cada punto rexistrado: 1,12–1,42× o rendimento de preenchimento de MLX-LM e 1,31–1,37× o seu rendimento de descodificación. A comparación utiliza a ruta de xeración directa máis rápida de MLX-LM. Ambos os eixes horizontais usan escalas logarítmicas; ningún eixe vertical comeza en cero.
Rendemento de preenchido por lonxitude de aviso e rendemento de descodificación por lonxitude de contexto para Qwen3.6-35B-A3B Q4, lote 1, nun M5 Max de 40 núcleos e 128 GB. En dez lonxitudes desde 256 ata 128K tokens, Lily é máis rápido en cada punto rexistrado: 1,12–1,42× o rendemento de preenchido de MLX-LM e 1,31–1,37× o seu rendemento de descodificación. A comparación emprega a ruta de xeración directa máis rápida de MLX-LM. Ambos os eixes horizontais empregan escalas logarítmicas; ningún eixe vertical comeza en cero.

Deseñado para a plataforma local

Apple silicon non é unha GPU de centro de datos máis pequena. É unha plataforma de inferencia local completa coas súas propias características de hardware e software. A memoria unificada outórgalle a un único nodo un límite máximo moi elevado sobre cantos modelos e estados pode conter. Os aceleradores neuronais M5 absorben o traballo denso de matrices no preenchido. As ALU de vectores xestionan o resto limitado polo ancho de banda e de baixa reutilización na descodificación.

Qwen engade novas oportunidades de especialización: manter o enrutamento de expertos e o estado recorrente na GPU, eliminar intermedios innecesarios, superpoñer traballo independente, reutilizar datos KV compartidos e adaptar os núcleos á forma da carga de traballo.

Cunha optimización específica para o modelo e a plataforma, un Mac pode executar un modelo disperso grande de forma eficiente. O traballo futuro ampliará a cobertura en modelos, chips e cargas de traballo de servizo, e converterá os mecanismos validados aquí nunha configuración nunha política de tempo de execución máis xeral.

O principio xeral é adaptar o motor tanto á arquitectura do modelo coma ás rutas específicas de computación e memoria do hardware. A medida que os modelos de pesos abertos de vangarda e o hardware evolucionen, a inferencia local de alto rendemento dependerá cada vez máis de motores adaptados a ambos en vez de aqueles que abstraen as súas diferenzas.