On-device inferentie optimaliseren voor Apple silicon
Een aangepaste lokale engine die de prefill- en decode-doorvoer verbetert.
Hybride berekeningen op Apple silicon orchestreren een taak tussen geavanceerde intelligentie in de cloud en een lokaal model op de Mac. Cloudmodellen handelen onderzoek en redeneren af, terwijl een lokaal model werkt met privébestanden en apps op de Mac.
Wil deze taakverdeling naadloos aanvoelen, dan moet lokale inferentie gelijke tred houden met de rest van de taak. Dat vereist een engine die prompts snel kan verwerken en een hoge tokengeneratiesnelheid kan handhaven.
Lily, onze lichtgewicht lokale inferentie-engine, is specifiek gebouwd voor Apple silicon en Qwen3.6-35B-A3B, met afzonderlijke optimalisaties voor prefill en decode. De engine wordt binnenkort als open source uitgebracht.
Inleiding
Een veelgebruikte manier om LLM's op een Mac uit te voeren is met MLX, Apple's open-source machinelearningframework voor Apple silicon. De bijbehorende bibliotheek, MLX-LM, voegt de componenten toe die nodig zijn om tekst te laden en te genereren met een breed scala aan taalmodellen. Samen bieden MLX en MLX-LM een kant-en-klare, multifunctionele stack voor lokale LLM-inferentie.
Qwen3.6-35B-A3B is een spars model met een hybride architectuur: het gebruikt mixture-of-experts (MoE)-routering en combineert recurrente toestanden van vaste grootte met volledige aandacht. Deze architecturale keuzes verminderen de benodigde hoeveelheid berekeningen, maar creëren ook onregelmatige takenpakketten. Tokens routeren naar verschillende expertgewichten en recurrente toestanden zijn van nature sequentieel.
MLX-LM selecteert al geoptimaliseerde kernels voor inferentiefasen en veelvoorkomende taakvormen, maar de herbruikbare bewerkingen moeten vele modelarchitecturen ondersteunen. Een engine die is toegewijd aan Qwen kan zich specialiseren op model- en runtimeniveau, waarbij kernels, databeweging en planning worden gecoördineerd rond de vaste structuur van het model.
Lily implementeert deze specialisatie end-to-end in één proces. Een Rust-runtime laadt het modelcheckpoint en beheert de sessiestatus en generatielus, een OpenAI-compatibele chat-completions-API accepteert verzoeken en streamt tokens, en aangepaste Metal-kernels voeren Qwen-specifieke bewerkingen uit. Noch PyTorch, noch MLX bevindt zich in het uitvoeringspad.

We meten prefill- en decode-prestaties apart. Prefill-doorvoer legt vast hoe snel de engine de prompt verwerkt; decode-doorvoer legt vast hoe snel outputtokens worden gegenereerd.
We benchen Qwen3.6-35B-A3B op een enkele MacBook Pro met een M5 Max met een GPU met 40 cores en 128 GB unificatiegeheugen. Over tien promptlengten voor prefill en tien contextlengten voor decode, van 256 tot 128K tokens (K = 1.024), behaalt de engine gemiddeld 1,23× de prefill-doorvoer van MLX-LM en 1,35× de decode-doorvoer. Bij een prompt van 4K tokens en een decodecontext van 4K tokens bereikt de aangepaste engine 5.749,9 prefill-tokens per seconde en 186,6 decode-tokens per seconde, vergeleken met 4.737,5 en 140,9 voor MLX-LM. Tijdens een sessie met meerdere beurten accumuleren deze tijdsbesparingen met elke extra modelaanroep.

Vervolgens leggen we uit hoe de architectuur van Qwen modelspecifieke optimalisatiemogelijkheden creëert op Apple silicon. Daarna doorlopen we de resulterende wijzigingen voor prefill en decode. We behandelen ook waar verdere optimalisatie ophoudt rendabel te zijn, en sluiten af met een end-to-end vergelijking met MLX-LM.
Qwen-specifieke optimalisatiemogelijkheden op Apple silicon
Qwen creëert drie onderscheidende taakvormen
Qwen3.6-35B-A3B bevat 35 miljard parameters, maar activeert er slechts ongeveer 3 miljard voor elk token. Een router scoort 256 expertsubnetwerken en selecteert er acht, naast één gedeelde expert die elk token verwerkt. Dit sparse MoE-ontwerp vermindert berekeningen, maar produceert ongelijkmatig werk: experts ontvangen verschillende aantallen tokens en elk token vereist gewichten van een andere combinatie van experts.
Qwen combineert ook 10 volledige aandachtslaaglagen met 30 Gated DeltaNet-lagen. Deze twee laadtypes behouden eerdere informatie op verschillende manieren.
De aandachtslaaglagen gebruiken grouped-query attention (GQA). Qwen heeft 16 queryheads en twee key-value (KV)-heads, waarbij acht queryheads elke KV-head delen. Delen maakt de KV-cache kleiner en zorgt ervoor dat gecachte gegevens hergebruikt kunnen worden over queryheads heen. De cache slaat nog steeds nieuwe sleutels en waarden op voor elk token, waardoor elke decode-stap meer gegevens leest naarmate de context groeit.
Gated DeltaNet comprimeert eerdere informatie daarentegen in een recurrente toestand van vaste grootte. Een aangeleerde poort bepaalt hoeveel van de bestaande toestand behouden blijft, terwijl een delta-update informatie van het huidige token opneemt. Het model definieert deze updates recurrent, zodat elk token afhangt van de toestand die door het voorafgaande token is geproduceerd. Tijdens prefill kan een engine dezelfde berekening echter op twee manieren evalueren. Het kan de tokens rechtstreeks scannen terwijl de toestand wordt meegenomen, of de updates herorganiseren in blokken die meer matrixbewerkingen en token-niveau-parallelisme blootleggen. Welke aanpak sneller is, hangt af van de modeldimensies, de taak en de hardware.
Samen creëren deze structuren drie berekeningspatronen: ongelijke expertgroepen, aandacht over een groeiende cache en een recurrentie met een vaste grootte die direct of in blokken kan worden geëvalueerd.
Apple silicon biedt verschillende paden voor verschillende taken
Prefill verwerkt vele prompt-tokenactivatierijen tegelijk. De lokale taak die hier wordt beschouwd, decodeert doorgaans één verzoek tegelijk (batch 1) en verwerkt één nieuwe rij per stap. Dit verschil verandert hoe dezelfde modelgewichten worden gebruikt. Prefill kan elk blok gewichten hergebruiken over honderden of duizenden rijen. Decode kan dat grotendeels niet, aangezien elk nieuw token een andere passage door de gewichten vereist.
Apple silicon plaatst de CPU en GPU achter unificatiegeheugen: één fysieke geheugenpool die toegankelijk is voor beide. Hierdoor kan het model resident blijven zonder een afzonderlijke GPU-kopie bij te houden, maar het maakt databeweging niet gratis. Het lezen van gewichten en intermediaire waarden consumeert nog steeds geheugenbandbreedte, terwijl registers en andere on-chip opslag sneller maar vele malen kleiner zijn.
De M5 GPU biedt ook verschillende rekenpaden. De lineaire lagen van prefill gebruiken algemene matrix-matrixvermenigvuldiging (GEMM), waarbij een gewichtsmatrix op vele rijen tegelijk wordt toegepast. Compatibele GEMM's kunnen de Neural Accelerator in elke GPU-core gebruiken via Metal 4-tensorbewerkingen. Batch-1 decode gebruikt in plaats daarvan algemene matrix-vectorvermenigvuldiging (GEMV), waarbij dezelfde gewichten op één rij worden toegepast. Met weinig hergebruik van gewichten wordt GEMV voornamelijk beperkt door geheugenbandbreedte en is het beter geschikt voor de vector-ALU's van de GPU dan voor Neural Accelerators die zijn ontworpen voor matrixbewerkingen met groter datahergebruik.
Deze uitvoeringspaden zijn niet uniek voor Lily. MLX werkt via hetzelfde unificatiegeheugen en selecteert geoptimaliseerde matrix- en vectorkernels op basis van de taakvorm. De Qwen-implementatie van MLX-LM groepeert expertwerk al, evalueert Gated DeltaNet met een gefuseerde recurrente Metal-kernel en gebruikt GQA-bewuste aandacht. Deze capaciteiten vormen het gedeelde startpunt voor efficiënte Qwen-inferentie op Apple silicon.
Optimalisatiestrategie
Het transparantere bereik van Lily maakt het mogelijk om deze gedeelde uitvoeringspaden te coördineren rond de exacte architectuur en dimensies van Qwen. Het gebruikt fasespecifieke GPU-paden, brengt de expert-, recurrente en aannametaken van Qwen in kaart om databeweging te minimaliseren en selecteert kernels en lay-outs op basis van de gemeten taakvorm. De strategie kent drie onderdelen:
- Stem het GPU-pad af op de inferentiefase. Gebruik matrix-georiënteerde uitvoering wanneer prefill gewichten kan hergebruiken over vele rijen, en vector-georiënteerde uitvoering wanneer batch-1 decode één rij per keer verwerkt.
- Breng de structuur van Qwen over op de GPU en minimaliseer databeweging. Houd gewichten gecomprimeerd totdat ze worden gebruikt, organiseer gerouteerd expertwerk zonder terug te keren naar de CPU, behoud de Gated DeltaNet-toestand on-chip tijdens de recurrente scan en hergebruik de KV-gegevens die worden gedeeld door grouped-query attention.
- Pas kernels aan op de taakvorm. Selecteer binnen elke fase tegelgroottes, uitvoeringslay-outs en aandachtsPaden uit het beschikbare rijtal, de verdeling van de rijen over experts, de afmetingen van de bewerking en de huidige contextlengte.
De volgende secties lichten deze keuzes toe. Voor optimalisaties die zijn geëvalueerd in gematchte ablaties op een M5 Max, schatten we de effecten in door anderszins identieke engineconfiguraties te vergelijken die alleen verschillen in de onderzochte optimalisatie. Omdat deze experimenten versies van onze engine met zichzelf vergelijken, verklaren ze mechanismen in plaats van de eindresultaten te ontleden ten opzichte van MLX-LM.
Prefill: hergebruik gewichten en houd routering op de GPU
Prefill stelt vele tokenrijen tegelijk bloot, maar Qwen routeert die rijen ongelijkmatig over experts en werkt de recurrente toestand bij via de sequentie. De optimalisaties vallen in drie groepen: organiseer sparse expertwerk rond de gerouteerde rijen, houd de Gated DeltaNet-scan on-chip en verdeel lange prompts in begrensde fragmenten.

Optimaliseer sparse expert-berekeningen
Dequantiseer gewichten tijdens matrixvermenigvuldiging
Het Qwen3.6-35B-A3B-checkpoint gebruikt groepsgewijze affiene 4-bit kwantisatie. Elk gewicht wordt opgeslagen als een 4-bit integer code, terwijl elke groep van 64 gewichten een bfloat16-schaal en bias deelt die worden gebruikt om de waarden te reconstrueren. Dit reduceert het model met 35 miljard parameters van grofweg 70 GB aan bfloat16-gewichten tot een checkpoint van 19,4 GB, waardoor het praktisch haalbaar is om het model resident op de Mac te houden.
De Metal 4-tensorbewerking die wordt gebruikt voor matrixvermenigvuldiging consumeert bfloat16-operanden in plaats van de gepakte 4-bit representatie. Vóór de vermenigvuldiging moet de GPU de gewichten reconstrueren in bfloat16. De geoptimaliseerde gegroepeerde GEMM in Lily voert deze conversie uit voor één klein gewichtsblok tegelijk en houdt het resultaat lang genoeg in on-chip threadgroup-geheugen om het te vermenigvuldigen met de gerouteerde activatierijen. Accumulatie gebruikt 32-bits drijvende komma en de uitvoer wordt geschreven in bfloat16. De volledige uitgebreide gewichtsarray wordt nooit gecreëerd in unificatiegeheugen.
In de ablatie draait dequantisatie als een afzonderlijke bewerking: het breidt de 4-bit gewichten uit naar een bfloat16-array in unificatiegeheugen, waarna de matrixkernel die array weer inleest. Bij een prompt van 512 tokens verhoogde het verplaatsen van dequantisatie naar de gegroepeerde GEMM de end-to-end prefill-doorvoer met 77,4% door deze intermediaire schrijf- en leesstap te elimineren.
Houd expert-routering op de GPU
De gegroepeerde GEMM vereist dat de activatierijen die aan elke expert zijn toegewezen, bij elkaar worden opgeslagen. Na het selecteren van acht experts per token telt een histogram hoeveel toewijzingen naar elke expert zijn gegaan. Een prefix-scan zet die tellingen om in startoffsets, een scatter-stap plaatst rijen in hun expertgroepen en een blokkenkaart somt de matrixblokken van vaste grootte op die de gegroepeerde GEMM moet verwerken.
Het geoptimaliseerde pad houdt deze hele reeks in één opdrachtbuffer (een geordende batch GPU-bewerkingen) voor elk promptfragment. In plaats daarvan pauzeert een ablatie zodat de CPU de routeringsintermediairs kan inspecteren en de volgende bewerking kan indienen. Het toevoegen van het histogram en de prefix-scan op de GPU voegt twee kernels toe, maar verwijdert de CPU-GPU-synchronisatie binnen elke MoE-laag.
Bij een prompt van 512 tokens verhoogde het inschakelen van GPU-resident routering de end-to-end prefill met 89%. Dit laat ook zien waarom alleen het aantal kernels misleidend kan zijn: de snellere route start meer kernels op, maar wacht nooit op de CPU binnen de laag.
Stem de tegelgrootte af op de expertbelasting
Bij een prompt van 2K tokens produceert het routeren van elk token naar acht van de 256 experts 16.384 token-experttoewijzingen, ofwel gemiddeld 64 activatierijen per expert. De daadwerkelijke verdeling is ongelijkmatig: sommige experts ontvangen veel rijen, terwijl andere er weinig ontvangen.
De gegroepeerde GEMM verdeelt de uitvoer van elke expert in tegels (kleine rechthoekige blokken van de uitvoer van een matrixvermenigvuldiging). Elke tegel wordt toegewezen aan één GPU-threadgroup. Op de GPU's van Apple silicon bevat een threadgroup één of meer simdgroups, die elk bestaan uit 32 draden die instructies in lockstep uitvoeren.
Grotere tegels spreiden de instelkosten over meer rijen en stellen meer parallel werk bloot, maar een deel van een grote tegel blijft inactief wanneer een expert slechts een paar rijen ontvangt. Tegelgrootte en het aantal simdgrouptaken zijn daarom gekoppeld.
Een ablatie zet de tegel vast op 16 rijen. Ten opzichte van die controlegroep verbeterde het inschakelen van de tegel van 32 rijen met vier simdgrouptaken de end-to-end prefill met 13,2% bij 2K tokens.
Houd recurrente toestand on-chip
Tijdens prefill scant elke Gated DeltaNet-laag de prompt op volgorde terwijl de recurrente toestand wordt meegenomen. Met registerresidency uitgeschakeld, gebruikt de ablatie een bloksgewijze scan. Bij een prompt van 2K tokens verplaatst dat pad 256 MiB (mebibytes) aan toestand per laag en stopt het herhaaldelijk samenwerkende draden bij barrières (synchronisatiepunten waar alle deelnemende draden op elkaar moeten wachten).
De recurrente toestand is een matrix. De geoptimaliseerde kernel wijst elke kolom toe aan één simdgroup. De simdgroup verdeelt de kolom onder zijn draden, laadt de kolom één keer in hun registers en voert de toestand door de hele scan. De draden wisselen tussenresultaten uit via simdgroup-bewerkingen in plaats van threadgroup-geheugen (on-chip opslag die wordt gedeeld over een threadgroup). De voltooide toestand wordt pas na de scan teruggeschreven.
De toestand en bijbehorende poort gebruiken een 32-bits drijvende-komma-indeling omdat kleine afrondingsfouten zich opstapelen bij sequentiële updates. Query- en sleutelactivaties blijven in bfloat16.
Bij een prompt van 2K tokens verbeterde het inschakelen van de scan in registers de end-to-end prefill met 5,6%. Expert-GEMM's waren goed voor ongeveer 90% van de prefilltijd. De sequentiële scan stelt niet genoeg herbruikbaar matrixwerk bloot om te profiteren van de Neural Accelerators.
Begrens tijdelijk geheugen met prompt-chunking
De runtime verwerkt een lange prompt als een reeks begrensde fragmenten in plaats van tijdelijke gegevens voor elk prompttoken tegelijk in het geheugen te bewaren. Modelgewichten blijven resident in het unificatiegeheugen, terwijl de recurrente toestand en KV-cache de context van het ene fragment naar het volgende dragen. Eerdere context wordt niet weggegooid.
Zonder chunking groeien tijdelijke activatie-arrays mee met de volledige prompt en concurreren ze met modelgewichten, recurrente toestand en de KV-cache om unificatiegeheugen. Chunking houdt de tijdelijke waarden van slechts één segment tegelijk actief en geeft die opslag vervolgens vrij of hergebruikt deze voordat het volgende segment wordt verwerkt. Dit plafond beperkt het piekgeheugen en stelt de engine in staat langere prompts te verwerken zonder de uitvoer van het model te veranderen.
Gecnkunkte prefill is populair in vele engines en is cruciaal voor het bedienen van lange multi-turn trajecten in deze geheugenbeperkte omgevingen. De totale prefilltijd voor aandachtslaaglagen blijft kwadratisch op de promptlengte, met enige toegevoegde overhead door herhaalde KV-ladingen van eerdere fragmenten.
Decode: minimaliseer de verplaatste bytes per token
Batch-1 decode verwerkt één nieuwe rij per stap. Met weinig hergebruik van gewichten hangt de doorvoer voornamelijk af van hoeveel bytes de engine verplaatst voor elk token. De decode-wijzigingen vallen in vier groepen: optimaliseer het gewichtspad met één rij, houd elke stap op de GPU, verminder intermediair en toestandsverkeer en lees de aandachts-cache efficiënt uit.

Optimaliseer het gewichtspad met één rij
MLX dispatcht werk met één rij al naar gespecialiseerde matrix-vectorkernels. Omdat Lily geen MLX gebruikt, moet de aangepaste runtime dezelfde basisstrategie bieden. Onze rij-parallele GEMV is ontworpen voor één activatierij. Een simdgroup werkt samen aan de uitvoer terwijl verschillende delen van de gewichtsmatrix parallel worden gelezen.
Houd elke decode-stap op de GPU
Houd de tokenoverdracht op de GPU
Elke decode-stap eindigt met het selecteren van het volgende token; de volgende stap begint met dat token als invoer. Het verzenden van de selectie naar de CPU en vervolgens terug naar de GPU voegt een synchronisatiepunt toe aan elk token. Onze runtime wisselt in plaats daarvan af tussen twee opdrachtbuffers en twee op de GPU residente tokensleuven. De GPU selecteert het token met de hoogste score en schrijft de token-ID rechtstreeks naar het invoersleufje voor de volgende decode-stap, terwijl de CPU volgend werk voorbereidt.
Laat onafhankelijk GPU-werk overlappen
In één geregistreerde decode-stap met batch-1 startte het genereren van een token 795 GPU-kernels. Hun afhankelijkheden vormden 555 sequentiële fasen, waardoor sommige kernels gelijktijdig konden draaien. De seriële uitvoeringsmodus van Metal voerde desalniettemin elke kernel op volgorde uit.
Het geoptimaliseerde decode-pad legt de daadwerkelijke data-afhankelijkheden vast in een gelijktijdige Metal-pass. Onafhankelijke kernelstarts kunnen tegelijkertijd draaien wanneer GPU-bronnen dit toelaten. Er wordt alleen een barrière ingevoegd wanneer later werk een eerder resultaat vereist.
Verminder intermediair en toestandsverkeer
Afzonderlijke kernels materialiseren vaak een tussentijds resultaat: de ene kernel schrijft een tijdelijk resultaat naar het geheugen en de volgende leest het resultaat weer terug. Het geoptimaliseerde decode-pad fuseert vier ketens: de twee expert-invoerprojecties met hun gegate activatie; de expert-uitvoerprojectie met zijn routeringsscore en het gedeelde-expertresultaat; de query- en sleutelvoorbereiding vóór aandacht; en de recurrente update met zijn normalisatie. Elke gefuseerde kernel houdt tijdelijke waarden in registers in plaats ze door het geheugen te sturen.
Fusie verkort ook de afhankelijkheidsgraaf: wanneer een intermediaire schrijfopdracht verdwijnt, verdwijnt ook de barrière die de consument beschermde.
Lees de aandachts-cache efficiënt uit
Voeg aandachts-cache-lezingen samen
Aandacht leest sleutels en waarden uit de KV-cache tijdens elke decode-stap. In de ablatie vragen naburige GPU-draden niet altijd om naburige bytes, waardoor het geheugensysteem meer afzonderlijke transacties moet afhandelen. Het inschakelen van samengevoegde leningen zorgt ervoor dat aangrenzende draden om aangrenzende bytes vragen zodat de hardware hun lezingen kan combineren.
In de bfloat16-configuratie verhoogde het samenvoegen de sleutelbandbreedte van 33,8 naar 47,9 GB/s, de waarde-bandbreedte van 42,0 naar 61,8 GB/s en verbeterde het de end-to-end decode met 2,1% bij een context van 3.840 tokens.
Pak queryheads in om KV-rijen te hergebruiken
Grouped-query attention laat acht queryheads één KV-head delen. In de ablatie draait elke queryhead in een aparte simdgroup, waardoor alle acht onafhankelijk dezelfde gecachte KV-rij opvragen. De geoptimaliseerde kernel groepeert vier queryheads in één threadgroup, die elke KV-rij één keer laadt en hergebruikt voor vier aandachtsberekeningen. Een tweede threadgroup verwerkt de resterende vier heads.
Deze techniek, algemeen GQA-groepering genoemd, voert dezelfde berekening uit en produceert identieke outputbytes terwijl acht onafhankelijke KV-verzoeken worden teruggebracht tot twee gedeelde leningen. Tegenover de ongepakte ablatie verbeterde het de end-to-end decode-doorvoer met 23,8% bij een context van 32K tokens.
Schakel aandachts-lay-outs bij lange contexten
Elke decode-stap in een laag met volledige aandacht scant de bestaande KV-cache. Een lay-out met vaste blokken verdeelt die cache in gelijke stukken die de GPU parallel kan verwerken. Extra planning is niet de moeite waard wanneer de cache klein is, maar de lay-out met vaste blokken brengt het werk meer in evenwicht naarmate de context groeit.
Voor dit model houdt de runtime het algemene aandachtsspoor onder 32K tokens en gebruikt het het vaste-blokspoor bij 32K of langer. De wissel is van toepassing wanneer elke head 256 waarden heeft en acht queryheads één KV-head delen; andere vormen blijven op het algemene pad. Een ablatie schakelt deze wissel uit en gebruikt altijd het algemene pad. Het inschakelen van de vaste-blokroute verbeterde de end-to-end decode met 7,7% bij 32K, 27,4% bij 64K en 40,2% bij 128K.
Grenzen van verdere optimalisatie
Sommige wijzigingen verbeterden een geïsoleerde bewerking, maar verbeterden de end-to-end inferentie niet.
Speculatieve decodering, waarbij een kleiner model tokens voorstelt die het volledige model moet verifiëren, maakte batch-1 decode 18% trager. Verificatie verwerkte groepen van twee tot vijf rijen (een inefficiënte vorm voor deze hardware) en de rijen selecteerden vaak verschillende experts, waardoor de hoeveelheid gelezen expertgewichtsdata toenam. Het verkleinen van de uitvoervocabulair van de opsteller verbeterde de doorvoer van de opsteller met 4,7–5,1%, maar maakte de complete speculatieve lus niet sneller. Dit resultaat is taakspecifiek: onze gebatchte Qwen-implementatie op Blackwell gebruikt speculatieve decodering onder andere omstandigheden.
Andere experimenten omvatten het verminderen van GPU-starts, het overlappen van volledige fasen, het gebruik van grotere prefill-tegels, het toepassen van bredere fusie, het versnellen van de router en het combineren van de uitvoerprojectie met tokenselectie. Geen enkele verbeterde de complete inferentielus.
Metingen van de hardwaregrenzen toonden ook weinig resterende ruimte in de hoofdprefill- en decodebewerkingen. De MoE GEMM's en GEMV's bereikten respectievelijk 97,9% en 90,3% van de snelste duurzame gewichtsleessnelheden voor hun toegangspatronen. Het verwijderen van rekenkundige bewerkingen uit de sparse GEMV veranderde de doorvoer met slechts 0,2%, wat bevestigt dat het lezen van gewichten in plaats van berekeningen de beperkende bron was. De matrixvermenigvuldiging van prefill bereikte op vergelijkbare wijze 93% van de theoretische matrixlimiet in isolatie en 80–86% binnen de geteste modellen.
End-to-end prestaties
De end-to-end vergelijking laadt identieke 4-bit checkpointbytes in beide engines en voert één verzoek tegelijk uit op één M5 Max met 40 cores en 128 GB. Binnen elke ronde draaien de twee engines in afwisselende volgorde om vertekening door achtergrondbelasting en veranderingen in chiptemperatuur te verminderen. We vergelijken met het snelste directe generatiepad van MLX-LM, niet de server, zodat de meting zich richt op modeluitvoering in plaats van overhead bij het serveren.
De sweep beslaat tien promptlengten voor prefill en tien contextlengten voor decode, van 256 tot 128K tokens. De prefill-doorvoer stijgt eerst naarmate de engine vaste instelkosten over meer tokens spreidt. Prefill piekt rond een prompt van 4K tokens en daalt daarna omdat de tien full-attention-lagen meer werk verrichten naarmate de prompt groeit. Decode blijft nagenoeg vlak bij korte contexten en neemt af zodra het lezen van de groeiende KV-cache significant wordt. De aangepaste engine is bij elke geregistreerde lengte sneller.
Omdat gespecialiseerde uitvoering de volgorde van drijvende-komma-bewerkingen kan wijzigen, hebben we ook de numerieke consistentie gecontroleerd tegenover MLX-LM. In een teacher-forced vergelijking voorspelden beide engines het volgende token uit hetzelfde referentieprefix op elk van de 192 posities, waarmee werd voorkomen dat eerdere verschillen latere invoer beïnvloedden. De perplexiteit van Lily was slechts 0,04% hoger en het selecteerde hetzelfde hoogst gewaardeerde token op 96,35% van de geteste posities.

Gebouwd voor het lokale platform
Apple silicon is geen kleinere datacenter-GPU. Het is een compleet lokaal inferentieplatform met eigen hardware- en softwarekenmerken. Unificatiegeheugen geeft een enkel knooppunt een zeer hoge limiet voor hoeveel model en toestand het kan vasthouden. De M5 Neural Accelerators absorberen het dichte matrixwerk in prefill. De vector-ALU's verwerken het bandbreedtegebonden, weinig hergebruikte restant in decode.
Qwen voegt verdere kansen voor specialisatie toe: houd expert-routering en recurrente toestand op de GPU, elimineer onnodige intermediairs, laat onafhankelijk werk overlappen, hergebruik gedeelde KV-gegevens en pas kernels aan op de taakvorm.
Met model- en platformspecifieke optimalisatie kan één Mac een groot spars model efficiënt uitvoeren. Toekomstig werk zal de dekking over modellen, chips en servicetaken uitbreiden en de hier gevalideerde mechanismen op één configuratie omzetten in een algemener runtimebeleid.
Het bredere principe is om de engine af te stemmen op zowel de architectuur van het model als de specifieke reken- en geheugenpaden van de hardware. Naarmate geavanceerde open-weight-modellen en hardware evolueren, zal high-performance lokale inferentie steeds afhankelijker worden van engines die op beide zijn afgestemd in plaats van op systemen die hun verschillen abstraheren.