Avançado

MLX

O framework de arrays da Apple: lazy evaluation, memória unificada e o mlx-lm rodando artefatos quantizados do Qwen3.8-27B — com o fit decidido pelo working set realizado, não pela capacidade de catálogo.

Atualizada em

01 · Conceito

Conceito

Aqui vai uma questão de compra que uma ficha técnica não responde. Você tem um desktop com uma GPU discreta de 24 GB e um Mac com 32 GB de memória unificada e quer rodar o Qwen3.8-27B quantizado com documentos longos. A GPU discreta pode oferecer banda muito maior; o Mac expõe outra topologia de memória. Qual deployment funciona melhor depende do working set realizado e do throughput medido, e entender por quê é a razão de existir do MLX.

O MLX é um framework de arrays feito para o Apple silicon, com uma API deliberadamente próxima do NumPy e uma camada de redes neurais próxima do PyTorch, então a maior parte do código de modelo se lê como você espera. Duas decisões de design o tornam diferente, e ambas decorrem do hardware.

A primeira é a lazy evaluation. Escrever uma expressão no MLX não a computa. Ela registra um nó num grafo de computação, e o grafo é executado quando algum valor é genuinamente requerido — quando você o imprime, converte ou força a avaliação explicitamente. Isso não é um truque de performance aparafusado depois; é o modelo de execução padrão. O retorno é que cadeias de operações podem ser fundidas em menos kernels e arrays intermediários que ninguém lê nunca precisam ser materializados. O custo é que cronometrar uma linha de código não mede nada: o trabalho que você acha que acabou de fazer provavelmente ainda não aconteceu, o que derruba todo recém-chegado que faz benchmark de um forward pass.

A segunda é a memória unificada, e é ela que responde à questão de compra. Num acelerador convencional, memória de host e memória de device são pools separados conectados por um barramento; um tensor existe num lugar, e usá-lo em outro significa uma cópia explícita. Arrays do MLX vivem em memória que tanto a CPU quanto a GPU endereçam diretamente. Uma operação é escalonada num device; o array não se move. Não existe .to(device) no modelo mental, não existe estágio de pinned memory e — criticamente — não existe teto definido por um orçamento separado de VRAM. O working set do modelo é limitado pela RAM do sistema e por quanto dela a GPU tem permissão de segurar, não por 24 GB soldados.

Não transforme a capacidade de memória unificada numa conta teórica de fit. A lição 7.2 é dona da derivação de KV cache e estado recorrente do Qwen3.8-27B, e a lição 9.3 é dona do orçamento completo de memória. O estado Gated DeltaNet da implementação de referência ocupa cerca de 144 MiB por sequência quando armazenado em fp32, constante no comprimento do contexto; o MLX pode usar outro dtype ou layout, enquanto alocações do Metal, sistema operacional e picos de avaliação do grafo saem do mesmo pool físico. Carregue o artefato convertido exato, force a avaliação e meça o pico do working set no contexto e na concorrência pretendidos antes de decidir se uma máquina de 32 GB ou 64 GB tem folga utilizável.

mlx_lm.convert --hf-path Qwen/Qwen3.8-27B -q --q-bits 4 --mlx-path qwen3.8-27b-4bit
mlx_lm.generate --model qwen3.8-27b-4bit --temp 0.7 --top-p 0.80 \
  --top-k 20 --min-p 0 --chat-template-config '{"enable_thinking":false}' \
  --prompt "..."

O pacote mlx-lm fornece as implementações dos modelos, o caminho de conversão e quantization a partir de um checkpoint do Hugging Face, a geração e um servidor local. O segundo comando desliga explicitamente o thinking pelo template e passa todas as partes do preset instruct do card que essa CLI fixada expõe: temperature 0.7, top_p 0.80, top_k 20 e min_p 0. Omitir --top-k 20 não preservaria o preset, porque o mlx-lm usa top-k 0 por padrão, o que desliga esse filtro. Essa revisão da CLI não tem flags de presence penalty nem repetition penalty; portanto, o comando é uma implementação parcial e declarada do preset completo do card, não uma reprodução exata. A mesma disciplina da lição 8.8 vale aqui: declare a configuração efetiva e os campos sem suporte em vez de herdar padrões em silêncio.

Duas coisas decorrem de esse comando de conversão ter uma linha só. A primeira é que você raramente precisa rodá-lo: a maioria das pessoas baixa a saída de outra pessoa, e no caso do MLX essa outra pessoa costuma ser a organização mlx-community no Hub, que hospeda conversões de um número muito grande de modelos. Pertencer a essa organização significa que uma conversão foi subida, não que ela foi avaliada — a lição 7.13 trata de distinguir essas duas coisas. A segunda é que --q-bits 4 é a versão grosseira da ferramenta. O mlx-lm também traz receitas mistas, que atribuem larguras diferentes a camadas diferentes (mixed_2_6, mixed_3_4, mixed_3_6, mixed_4_6), e um caminho de learned quantization cujo --target-bpw recebe uma média como objetivo e descobre sozinho a atribuição por camada. É daí que vem um checkpoint anunciando bits por peso fracionário, e é por isso que um número como 3,8 é um ajuste, não um engano.

A virada errada clássica é escolher apenas pela capacidade de catálogo. O tamanho do artefato não é o working set completo em nenhuma das máquinas: pesos, cache, estado recorrente, buffers de runtime e concorrência dividem o pool disponível, e seus dtypes e layouts realizados pertencem ao runtime exato. Uma GPU discreta em geral oferece banda de decode maior enquanto o working set medido cabe; se ela exige spill para CPU, o PCIe pode virar o gargalo. A memória unificada remove a fronteira explícita de cópia entre host e device e pode expor um pool compartilhado maior, mas o sistema operacional e o Metal competem por ele, e swap não é capacidade utilizável de serving. Faça benchmark do artefato e da carga exatos nos dois caminhos; não deduza o vencedor de 24 GB contra 32 GB.

A ideia durável é que a topologia de memória é uma escolha arquitetural com consequências que uma ficha técnica esconde. Grafos lazy compram fusão; memória unificada compra teto. A lição 9.6 leva a sério o lado da banda desse acordo e calcula quantos tokens por segundo o arranjo consegue de fato sustentar.

02 · Analogia

Analogia

Dois cozinheiros preparam o mesmo prato. Um tem um fogão enorme e potentíssimo numa sala separada e um corredor estreito até a despensa; cada ingrediente precisa atravessar o corredor antes de poder ser cozido, e o fogão fica ocioso sempre que o corredor está ocupado. O outro tem um fogão menor bem no meio da despensa — mais lento por panela, mas nada é carregado a lugar nenhum, e não existe prato grande demais para a sala. Memória unificada é a segunda cozinha.

03 · Explique de volta

Explique de volta

Explique as duas decisões de design que definem o MLX, depois explique como você validaria um deployment do Qwen3.8-27B em 4 bits num Mac de 32 GB e o compararia honestamente com uma GPU discreta de 24 GB.

Mínimo: 80 caracteres e 15 palavras. Seu texto fica somente neste navegador.

Aguardando sua explicação.

Comparar com uma resposta-modelo

O MLX é lazy e unificado. As operações constroem um grafo e se materializam quando um valor é necessário ou quando a avaliação é forçada, permitindo fusão e evitando temporários que ninguém lê. Arrays vivem em memória compartilhada por CPU e GPU, então escalonar uma operação não exige cópia de host para device. Um artefato do Qwen3.8-27B em 4 bits pode colocar os 17,1 GB (15,93 GiB) do artefato de texto Q4_K_M fixado nesse pool, mas isso não prova que cabe. A lição 7.2 é dona da derivação de cache e estado recorrente, incluindo cerca de 144 MiB por sequência para o estado DeltaNet em fp32 da referência; a lição 9.3 é dona do orçamento completo de memória. O MLX pode usar outro dtype ou layout de estado, e Metal, sistema operacional e grafo de compute dividem a memória do sistema. Meça o working set realizado no contexto e na concorrência pretendidos. Compare o resultado com throughput e alocação realizados na GPU discreta: o device discreto costuma ganhar em banda enquanto tudo cabe, enquanto a memória unificada muda a topologia e o pool disponível, não a necessidade de folga.

04 · Teste seu entendimento

Teste seu entendimento

01Por que o artefato de texto Q4_K_M fixado tem 17,1 GB, e não os 13,5 GB da estimativa ingênua baseada no rótulo arredondado 27B?
Resposta e explicação

A quantization é por grupos: cada grupo de pesos carrega uma escala, e muitas vezes um zero point, armazenados junto dos códigos empacotados — A lição 7.9 estabeleceu que formatos de poucos bits quantizam em grupos pequenos e precisam distribuir os metadados de escala por grupo, então os bits efetivos por peso sempre excedem a largura nominal.

02No MLX, o que dispara a computação efetiva de uma expressão de array?
Resposta e explicação

A avaliação é lazy: o grafo é computado quando um valor é necessário ou quando a avaliação é forçada explicitamente — A lazy evaluation é uma das duas escolhas definidoras do MLX; é o que permite ao framework fundir cadeias de operações e nunca materializar temporários que ninguém lê.

Conclua o teach-back e acerte o quiz para finalizar a aula.

◎ · Marcador de evidência

Fontes

  1. Apple Machine Learning Research (2026). MLX Documentation.
  2. Apple Machine Learning Research e contribuidores (2024). mlx-lm.
  3. Apple Machine Learning Research e contribuidores (2026). mlx-lm generate.py — código-fonte fixado da CLI.
  4. Qwen Team (2026). Qwen3.8-27B Model Card.