Pare de Deixar suas GPUs Ociosas: um playbook de CTO para throughput de tokenização

Por Diogo Hudson Dias
Server monitor showing low GPU utilization and a CPU graph at 100% in a modern office.

Suas GPUs não são lentas. Elas estão esperando. Se você vê a utilização cair para 40–60% no momento em que um prompt longo chega, isso não é problema do modelo — é o tokenizer estrangulando o pipeline. A indústria está acordando para isso. Novas pesquisas já falam em acelerações de ordem de grandeza na tokenização, e engenheiros trocam dicas de SIMD porque isso impacta dinheiro de verdade. Se você roda LLMs em produção, tokenização não é side quest. É a diferença entre pagar 1 ou 2 GPUs para a mesma vazão.

Por que a Tokenização Virou o Gargalo

O tráfego moderno de LLM mudou em três dimensões:

  • Contextos mais longos. Entradas de 32K, 64K e até 128K tokens são rotina em RAG e revisão de código. Codificar 100–400 KB de texto Unicode misto pode consumir de centenas de milissegundos a múltiplos segundos em um único core de CPU.
  • Maior concorrência. Agentes e UX de streaming multiplicam as requisições paralelas. Se cada requisição fixa um core para codificar/decodificar, você bate no teto de CPU muito antes de saturar as GPUs.
  • Mais tráfego multilíngue. Scripts mistos (português + inglês + emojis + código) estressam tokenizers de subpalavras e caminhos de normalização Unicode, que são pesados de CPU a menos que vetorizados.

Em muitas pilhas, a anatomia de uma requisição é assim:

  1. Codificar o texto do prompt em tokens na CPU.
  2. Rodar a inferência na GPU.
  3. Decodificar os tokens de volta para UTF‑8 na CPU enquanto faz streaming.

Você paga duas vezes: uma no início (a latência de codificação atrasa o time‑to‑first‑token), e outra no fim (a vazão de decodificação dita a fluidez do stream). Se qualquer um não for rápido, a ocupação da GPU despenca e o p95 estoura — especialmente em sistemas multi‑tenant.

Como Saber se Tokenização é o Problema Real

  • Cliff de ocupação da GPU: a utilização cai >20 pontos percentuais quando chegam prompts grandes; depois volta a subir no meio da geração.
  • TTFT vs. tamanho do prompt: o time‑to‑first‑token escala aproximadamente de forma linear com os bytes do prompt mesmo quando o modelo está em cache. Isso é codificação, não o LLM.
  • Padrão de consumo de CPU: 1 core por requisição em 100% no pré e pós‑inferência, com traces de desempenho presos em funções do tokenizer.
  • Travadas na decodificação: streams “engasgam” com chunks SSE pequenos e CPU alta mesmo quando o modelo está emitindo tokens rapidamente.

Se você vê dois dos itens acima, está limitado por tokenização.

A Matemática do Retorno (Por que se Importar Neste Trimestre)

Suponha que um modelo 7B–13B em uma única GPU moderna gere ~150–300 tokens/seg. Se codificar 20K tokens de entrada leva 600 ms de CPU e decodificar 10K tokens de saída leva mais 300 ms ao longo do stream, então, em uma interação de 15 segundos, você desperdiça ~6%–10% do tempo de parede em estágios de CPU. Em escala, isso é 6%–10% a menos de ocupação de GPU e custo por token correspondemente maior.

Esse é o cenário otimista. Em contextos mais longos (64K+), Unicode misto ou sob concorrência, medimos rotineiramente 30%–50% do tempo de parede consumido pela tokenização a menos que você otimize. Se sua instância classe H100 custa dezenas de dólares por hora, cada 10 pontos percentuais de ocupação recuperada é material.

Framework de Decisão do CTO: 6 Alavancas que Realmente Fazem Diferença

1) Use um Tokenizer Moderno e Vetorizado

Pare de usar caminhos legados presos ao Python para codificar/decodificar. Migre para implementações de alto desempenho em Rust/C++ com SIMD.

  • Hugging Face Tokenizers (Rust) com bindings é o baseline padrão. Compile com flags específicas do alvo (AVX2/AVX‑512 em x86; NEON/SVE em ARM) e verifique que estão ativas em produção.
  • SentencePiece (C++) pode ser rápido quando compilado com as flags adequadas e vinculado sem fallbacks lentos de locale/ICU.

O que esperar: acelerações de 2–5x sobre caminhos ingênuos em CPUs genéricas de cloud; mais em AVX‑512 ou Apple Silicon com NEON quando o build está correto.

2) Faça Batch de Codificação e Decodificação — Mesmo Entre Tenants

Tokenizers vetorizam melhor em lotes. Não codifique/decodifique uma requisição por vez.

  • Tamanho de batch 8–32 é um bom começo; mire em <25 ms de espera em fila para manter o p95 sob controle.
  • Em sistemas movimentados, micro‑batches cross‑tenant entregam consistentemente 1,5–3x de throughput em cod/dec e curvas de CPU mais suaves.

Trade‑off: p50 ligeiramente maior; p95/p99 menores devido à redução de thrash na CPU.

3) Defina Afinidade e Isole o Hot Path

Tokenização é sensível a cache. Trate como se fosse um banco de dados:

  • Pine workers do tokenizer a cores dedicados de CPU. Mantenha‑os fora do mesmo nó NUMA dos seus interrupts de rede.
  • Pré‑aqueça e fixe o vocabulário em memória. Use mmap para grandes tabelas de trie/merges a fim de aproveitar o page cache do SO; considere hugepages para reduzir TLB misses.
  • Mantenha local à GPU que servem (mesmo host) para evitar latência de hop de rede se você separar em um microsserviço.

Espere ganhos de 1,2–1,8x apenas removendo crosstalk e churn de páginas.

4) Normalize Unicode Uma Vez, de Forma Consistente

Entradas mistas (acentos em português, emojis, código) causam caos se você normalizar de forma inconsistente. Decida por NFC (mais comum) ou o esquema exigido pelo modelo e faça isso uma única vez, antes da tokenização. Depois, reutilize a mesma política na decodificação.

  • Normalização inconsistente custa CPU e altera fronteiras de tokens, quebrando caches e a reprodutibilidade de avaliações.
  • Centralize isso em uma biblioteca única compartilhada pelos seus serviços; não confie nos padrões específicos de cada linguagem.

5) Faça Cache Onde Importa (e Versione)

Você não consegue colocar tudo em cache, mas consegue cachear o que é caro e repetido:

  • Prompts de sistema e templates de instrução de cada persona de ferramenta/agente. Faça o key por um hash de conteúdo que inclua o tokenizer/versão.
  • Chunks populares de retrieval em RAG. Se seu índice retorna os mesmos 50 parágrafos 10K vezes/dia, faça cache das formas tokenizadas.
  • Shards de decodificação para boilerplates estáticos que o modelo emite com frequência (headers, disclaimers). É de nicho, mas eficaz em apps com forte compliance.

Seja rigoroso com invalidação de cache: hash(tokenizer binary + merges/vocab + política de normalização + conteúdo). Faça roll forward nos caches em qualquer mudança para evitar bugs silenciosos de correção.

6) Escolha o Silício Certo — e Compile para Ele

Tokenização é um jogo de CPU hoje. Dois ângulos práticos:

  • x86 com AVX‑512/AVX2: Lanes SIMD enormes ajudam em merges de BPE/SentencePiece e varreduras Unicode. Verifique as flags em runtime; distribua binários separados se necessário.
  • ARM (AWS Graviton/Apple Silicon): NEON é excelente para classificação UTF‑8 e ops vetoriais. Builds bem ajustados competem com x86 com melhor $/core na nuvem. Teste Graviton para microserviços de cod/dec mesmo que suas GPUs estejam em outro lugar.

Há trabalhos experimentais movendo tokenização para a GPU. É promissor em cenários de batch extremo, mas adiciona pressão de memória e complexidade de engenharia. Para a maioria das equipes, tokenização rápida em CPU + batching é o 80/20.

Um Plano de Implementação para Entregar em 30–60–90 Dias

Dia 0–30: Instrumentar, Estabelecer Baseline, Quick Wins

  • Adicione quatro métricas ao seu gateway de inferência: encode_ms, decode_ms, tokens_in, tokens_out por requisição; além de time_to_first_token e utilização de GPU.
  • Migre para um tokenizer em Rust/C++ com SIMD ligado. Confirme com um feature probe (por exemplo, logando a ISA detectada na inicialização).
  • Normalize uma vez para NFC na entrada. Adicione um teste de laboratório que faça diff da tokenização antes/depois para garantir ausência de drift de comportamento.
  • Habilite batching para cod/dec em 8–16 itens com janela de micro‑batch de 10–20 ms. Observe o p95.

Meta: 2–4x de throughput em cod/dec versus baselines presos ao Python, +10–20 pontos percentuais de ocupação de GPU em workloads mistos.

Dia 31–60: Isolar o Hot Path e Escalar

  • Separe a tokenização em um sidecar ou microsserviço no mesmo host de cada GPU, usando gRPC e um wire format binário para arrays de tokens.
  • Affinidade de CPU e pinagem de NUMA para os workers do tokenizer; deixe espaço para threads de rede e orquestração em outros lugares.
  • Pré‑carregue tabelas de vocabulário e merges na inicialização do processo; alerte se um caminho de leitura fria acontecer em produção.
  • Cache prompts de sistema comuns e chunks frequentes de RAG, indexados por um hash versionado rigoroso.

Meta: mais 1,5–2x de throughput em cod/dec e p95 mais suave. Meça custo por milhão de tokens antes/depois.

Dia 61–90: Otimize para o Seu Mix de Tráfego

  • Políticas de batching cientes do tenant. Para tenants de baixa latência, mantenha a janela de batch em 5–10 ms; para pools de throughput, permita 25–35 ms para empurrar o batch para 16–32.
  • Política de streaming na decodificação. Faça flush a cada 32–64 tokens (não a cada token). Usuários percebem fluxo melhor, as CPUs fazem menos syscalls e você reduz head‑of‑line blocking.
  • A/B de silício. Teste um pool Graviton para serviços de tokenizer. Compare $/token codificado e p95 fim‑a‑fim com x86. Em muitas clouds, ARM vence em preço sem perder desempenho.
  • Avalie tokenizers avançados. Projetos que prometem acelerações de ordem de grandeza estão surgindo. Faça piloto em shadow; garanta paridade exata de tokens antes do rollout.

Meta: chegar a uma política estável por classe de tráfego e consolidar melhorias de 5–10x em cod/dec em relação ao ponto de partida, ou o mais próximo que seus inputs permitirem.

Detalhes de Engenharia que Importam (e Vão te Morder se Ignorados)

Flags de Build e Binários

  • Distribua múltiplos builds para AVX‑512, AVX2 e baseline SSE2; selecione em runtime. Um binário lento “universal” é como você ganha regressões surpresa quando o scheduler move seu pod.
  • Em ARM, habilite NEON/SVE e verifique com log na inicialização. Muitas imagens base de container silenciosamente desabilitam isso.

Threading e Backpressure

  • Use filas com limite. Se o tokenizer não acompanhar, aplique backoff na entrada em vez de enfileirar sem limite e destruir o p99.
  • Dimensione pools de threads para cores físicos, não vCPUs. Oversubscription parece bom no dashboard e ruim no desempenho.

Layout de Memória e I/O

  • Mantenha merges/vocab contíguos; evite churn de heap pré‑alocando buffers para a maior requisição esperada no batch.
  • mmap artefatos somente leitura para que workers forkados os compartilhem. É “deduplicação” grátis no page cache.

Corretude e Atualizações

  • Trate o tokenizer como o modelo: versionamento semântico, golden tests e canary rollout. Mudanças de tokens quebram a paridade treino/inferência, caching e avaliações.
  • Para apps multilíngues (incluindo mercados de Brazil/LatAm), meça a inflação de tokens por idioma. Alguns tokenizers explodem diacríticos; outros não. Isso afeta diretamente o $/requisição.

Observabilidade: o que Colocar no Telão

  • Histogramas de ms de codificação / token e ms de decodificação / token, não apenas médias.
  • Ocupação de GPU sobreposta ao TTFT por faixa de tamanho de requisição (por exemplo, 0–8K, 8–32K, 32–128K tokens).
  • Tamanho de batch realizado vs. janela de batch por pool.
  • ISA do tokenizer em uso por host (AVX‑512/AVX2/NEON) e alertas sobre a mistura de arquiteturas.
  • Taxa de acerto de cache para prompts de sistema tokenizados e chunks de RAG.

Se você opera squads ou pods nearshore, dê a cada pod seu próprio dashboard. Problemas de tokenização são dependentes do workload; análise de fraude e agentes de código não se parecem em nada.

Cenários de Custo: a Matemática Chata que Conquista Orçamento

Suponha que você gaste US$ 100 por dia por GPU e rode 20 GPUs para carga constante: US$ 2.000/dia. Se a ineficiência de tokenização segura a ocupação em 60%, você está efetivamente pagando US$ 3.333/dia pelo trabalho que de fato recebe. Elevar a ocupação para 85% via um ganho de 5x em codificador/decodificador reduz o custo efetivo em ~29% (60 → 85). Mesmo que você consiga apenas 2x de forma conservadora, um ganho de 10–15 pontos percentuais em ocupação paga o esforço de engenharia em semanas.

É por isso que manchetes de “tokenização 1000x mais rápida” são interessantes, mesmo que você nunca alcance a promessa completa nos seus dados. Você não precisa de 1000x. Precisa do suficiente para mover ocupação e p95.

E Mover a Tokenização para a GPU?

Há trabalho ativo em tokenização e decoders residentes na GPU. Em cenários fortemente batcheados (vazão muito grande, requisições homogêneas), isso pode ajudar. Trade‑offs:

  • Pressão de memória: você está compartilhando HBM com o modelo e o KV cache.
  • Complexidade: você precisa manter paridade de tokens e correção Unicode entre kernels e versões.
  • Ganhos marginais se seu caminho em CPU já estiver bem otimizado e batcheado.

Nosso ponto de vista: prove que você espremeu o caminho em CPU (SIMD + batching + pinagem + cache) antes de adicionar kernels na GPU. Para a maioria das startups e scale‑ups, esse é o caminho de maior alavancagem em Q3–Q4.

Perspectiva Brazil/LatAm: Ganhos Baratos em ARM e Tuning Alinhado de Fuso

Se você opera pods nearshore no Brazil, coloque um trial de Graviton no roadmap. ARM NEON vai bem em caminhos pesados de UTF‑8, e regiões AWS São Paulo facilitam rodar microsserviços de tokenizer perto dos usuários mantendo 6–8 horas de sobreposição de jornada com times dos EUA. Temos visto 20–30% mais barato em $/token codificado em serviços de cod/dec de estado estacionário em ARM versus frotas x86 mais antigas, assumindo que você compile corretamente e fixe threads.

Por Onde Começar Amanhã de Manhã

  • Publique um RFC de uma página que declare: nosso binário de tokenizer, flags de build, política de normalização, metas de janela de batching e as quatro novas métricas.
  • Rode um A/B de 24 horas com SIMD ligado vs. desligado, batching ligado vs. desligado. Escolha o gráfico que te devolve +10 pontos de ocupação e congele a configuração.
  • Torne a tokenização um SLO de primeira classe: TTFT em N tokens e orçamento de encode_ms/token. Revise semanalmente como você revisa o p95.

Em Resumo

Seu modelo não é a parte lenta; seu tokenizer é. As equipes que vão obter economia desproporcional com LLMs em 2026 não estão só comprando GPUs maiores — estão alimentando melhor as que já têm. Trate tokenização como um sistema de produção com orçamentos, SLAs e responsáveis. Você entregará respostas mais rápidas, maior throughput e uma conta significativamente menor.

Principais Pontos

  • Tokenização hoje consome rotineiramente 10–50% do tempo de parede; consertar isso eleva a ocupação da GPU e reduz drasticamente o custo por token.
  • Vá para tokenizers em Rust/C++ com SIMD, faça batch de cod/dec entre tenants e fixe workers do tokenizer em cores dedicados.
  • Normalize Unicode uma vez, faça cache de prompts/chunks de alto reuso com hashes versionados rigorosos e meça encode_ms/token e decode_ms/token.
  • Espere melhorias de 5–10x em cod/dec com higiene básica; você não precisa de pesquisa de ponta para economizar dinheiro de verdade.
  • Considere ARM (Graviton) para serviços de tokenizer — frequentemente 20–30% mais barato com desempenho similar quando compilado corretamente.
  • Transforme tokenização em um SLO com responsáveis. É um estágio do pipeline, não uma chamada de biblioteca.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation