- Ferramenta alternativa ao Tiktoken e ao HuggingFace Tokenizers, com suporte a vários CPUs e tokenizadores amplamente usados, processando texto em GB/s
- Otimiza com SIMD a pré-tokenização normalmente feita por motores de regex, reduz ramificações, comunicação entre threads e interação com Python, além de fazer cache eficiente do mapeamento de tokens de palavras já vistas
- No benchmark de 11,9GB do OpenWebText, a vazão do GPT-2 chegou a 24.53GB/s em um AMD EPYC 9565, 8.79GB/s em um Apple M4 Max e 6.27GB/s em um Ryzen 7 9800X3D
- O modo de compatibilidade com HuggingFace e Tiktoken mantém quase todo o código existente intacto, mas perde desempenho pelo custo de reproduzir exatamente a mesma saída; a API do Gigatoken, em que o Rust lê os arquivos diretamente, oferece o maior paralelismo e a maior velocidade
- Ainda não há suporte a WordPiece nem saída para arquivo, e faltam otimizações para SentencePiece e validação no Windows, então no momento ele é mais adequado para tokenizadores BPE em Linux, macOS ou WSL
Escopo de suporte e modo de uso
- Gigatoken é um tokenizador de alta velocidade para modelos de linguagem, voltado a CPUs x86 e ARM modernas e a quase todos os tokenizadores comuns
- A instalação é feita com
pip install gigatoken, e ele oferece sua própria API e um modo de compatibilidade com HuggingFace Tokenizers e Tiktoken - O modo de compatibilidade encapsula tokenizadores existentes e os converte com
.as_hf()ou.as_tiktoken(), respectivamente- Aplica bastante trabalho para que a saída corresponda exatamente à do HuggingFace Tokenizers
- Esse processamento de compatibilidade tem um custo de desempenho nada desprezível, então não chega ao ganho de cerca de 1.000x da API própria, mas ainda assim é mais rápido que as implementações existentes no geral
- A API própria recebe nomes de modelos do HuggingFace como
"Qwen/Qwen3-8B"eTextFileSource, codificando arquivos diretamente- A implementação em Rust lê os dados diretamente, evitando overhead desnecessário e maximizando o paralelismo
- Ao passar estruturas de dados do Python, o custo de leitura dos dados no Python continua existindo
Implementação para aumentar a velocidade
- O maior ganho vem da reimplementação altamente otimizada, com base em SIMD, da pré-tokenização que normalmente é deixada a cargo do motor de regex
- O foco também foi minimizar ramificações e otimizar intensivamente o cache de mapeamento de pré-tokens, que busca os tokens codificados de palavras já vistas
- O cache cresce rapidamente e a distribuição dos pré-tokens tem cauda longa, o que dificulta seu tratamento
- Reduzir a interação com Python e a comunicação entre threads também trouxe ganho adicional de desempenho
- Não é uma implementação ajustada para um único CPU ou tokenizador específico: houve otimização para combinações de vários tokenizadores com CPUs x86 e ARM modernas, e os resultados se mantêm consistentes entre CPUs e tokenizadores
Benchmark de 11,9GB do OpenWebText
- Em um ambiente com AMD EPYC 9565 de 144 núcleos, a vazão do GPT-2 chegou a 24.53GB/s, sendo 989x mais rápida que os 24.8MB/s do HuggingFace Tokenizers e 681x mais rápida que os 36.0MB/s do Tiktoken
- As principais variantes de BPE ficaram em geral entre cerca de 15.49~24.00GB/s
- Itens baseados em SentencePiece foram relativamente mais lentos, com cerca de 2.51~4.82GB/s
- No Apple M4 Max de 16 núcleos, o GPT-2 chegou a 8.79GB/s, sendo 1.268x mais rápido que o HuggingFace e 140x mais rápido que o Tiktoken
- OLMo 2/3 registrou 1.299x em relação ao HuggingFace, e Qwen 2/2.5 registrou 1.105x
- No AMD Ryzen 7 9800X3D de 16 núcleos, o GPT-2 chegou a 6.27GB/s, sendo 106x mais rápido que o HuggingFace e 68x mais rápido que o Tiktoken
- As principais variantes de BPE ficaram em cerca de 4.21~6.09GB/s, enquanto variantes relativamente menos otimizadas ficaram em cerca de 1.12~2.84GB/s
Condições de medição e interpretação
- O OWT (OpenWebText) foi escolhido como dado de benchmark por representar aproximadamente o texto obtido após extrair documentos do Common Crawl
- O Gigatoken processa o arquivo inteiro sem dividi-lo previamente, então ele próprio executa a busca de limites de divisão e o paralelismo automático
- Os comparativos processam dados previamente divididos com base em
<|endoftext|>- O HuggingFace
encode_batch_fastusa os primeiros 100MB - O Tiktoken
encode_ordinary_batchusa o primeiro 1GB - Como nenhuma das duas implementações usa cache e a velocidade tende a permanecer estável ao longo do processamento, essas condições de comparação foram adotadas
- O HuggingFace
- Os resultados do Tiktoken incluem apenas tokenizadores oficialmente suportados
- Cada linha representa um único tokenizador distinto com o mesmo vocabulário, merges e pré-tokenizador
- Várias versões e modelos derivados das famílias Llama, Qwen, DeepSeek, GLM, Nemotron, Kimi, Phi e Gemma foram agrupados na mesma linha de tokenizador
- O item mais lento é o tokenizador baseado em SentencePiece, que ainda não foi suficientemente otimizado no Gigatoken
Validação de suporte e processamento em larga escala
- Sem instalar nada, é possível validar a tokenização de repositórios de modelos do HuggingFace e medir o tempo com o comando
uvx --with tokenizers gigatoken bench - No exemplo de validação do GPT-2, a saída bateu em 20.401 documentos
- No Apple M4 Max, processou 11,920.51MB em 1.432s, a 8,327.05MB/s, ficando 1,353.13x mais rápido que o HuggingFace
- No AMD EPYC 9565, processou os mesmos dados em 0.486s, a 24,532.45MB/s, ficando 989.21x mais rápido
- Nessa taxa do EPYC, seria possível tokenizar todo o Common Crawl, na escala de 130 trilhões de tokens, em menos de 6,5 horas
- O exemplo usa o sample OWT do Stanford CS336, e por padrão a CLI usa os primeiros 100MB do arquivo para validação e comparação com o HuggingFace
- Na primeira execução no macOS, o código Rust pode ficar mais lento por causa da verificação de segurança, então pode ser necessário rodar o comando duas vezes para uma medição precisa
- Casos de divergência na saída ou lentidão devem ser reportados em GitHub Issue
Limitações conhecidas
- O processamento iterativo em Python é executado em Rust, mas usa ABI3, que é mais lento que as APIs internas do CPython específicas por versão
- Há planos para especialização por versão do Python, e experimentos iniciais mostraram 2x de ganho em casos dominados por overhead
- A API do Gigatoken ainda não implementa um sink de saída para arquivo
- WordPiece não é suportado
- A tokenização baseada em SentencePiece tem um nível de otimização inferior ao BPE comum
- A prioridade atual também é baixa, principalmente porque é mais usada por modelos do Google e da família BERT
- Como os testes no Windows ainda não são suficientes, no momento o recomendado é usar WSL
Escopo do uso de IA
- A maior parte do codebase foi escrita diretamente, sem IA, e isso pode ser verificado no histórico de commits do projeto
- Na fase final do projeto, a IA foi usada nas seguintes tarefas
- implementação da API para usuários
- generalização, portabilidade e ampliação da compatibilidade do pré-tokenizador para mais tokenizadores
- suporte a padding, truncamento e normalização Unicode
- portabilidade das estratégias SIMD entre AVX512, AVX2 e NEON
- ganho final de cerca de 4x de desempenho com remoção de ramificações e melhorias na hierarquia de cache de pré-tokens
- refatoração e melhoria do reuso de código
1 comentários
Opiniões no Hacker News
Como “a maior parte do código foi escrita diretamente, sem IA, e isso pode ser verificado no histórico do Git”, a declaração de que a programação humana acabou perde força
Não se trata de otimizar excessivamente uma CPU específica e um único tokenizer, mas sim de obter desempenho consistente ao otimizar todo o conjunto de combinações entre x86·ARM modernos e vários tokenizers
A pré-tokenização, normalmente deixada para mecanismos de expressões regulares, foi otimizada diretamente com SIMD e com o mínimo de ramificações; também melhoraram o cache de mapeamento de tokens do vocabulário para encontrar rapidamente o resultado da codificação de palavras já vistas. Nessa área, os caches crescem rápido e têm caudas longas na distribuição, o que os torna difíceis de lidar
A interação com Python e a comunicação entre threads também foram minimizadas
Lembra o simdjson, que atinge velocidades difíceis de acreditar com programação criativa. Se for amplamente adotado, pode reduzir bastante energia, custos e emissões de carbono, então seria bom publicar também um crate em Rust; se necessário, eu mesmo gostaria de ajudar
Pensando em economia e meio ambiente, processamento em lote de requisições tem um efeito maior. O problema mais caro é a baixa utilização da GPU; ao adaptar o trabalho ao formato de processamento em lote, hoje já é possível economizar 50% até na OAI. Se nem todas as respostas precisam ser imediatas, algumas podem esperar alguns dias; chamadas de ferramentas não expiram, e para o próprio LLM não existe tempo de relógio de parede
Clonei o repositório e dei uma olhada: a substituição das expressões regulares de pré-tokenização e a otimização de cache são abordagens úteis de forma geral. É um trabalho excelente, a ponto de toda a comunidade de tokenização querer aprender o segredo desse ganho de velocidade
É uma conquista ótima, mas a tokenização normalmente representa menos de 0,1% do tempo total de inferência. Ainda assim, será muito útil para aplicações que precisam da tokenização em si
O efeito aumenta com modelos menores ou GPUs mais rápidas, e ainda é preciso validação adicional antes de incluir isso no README. A origem do benchmark é fastokens
Fonte: https://www.gartner.com/en/newsroom/press-releases/2026-07-2...
Parece mais útil na preparação offline de dados de pré-treinamento do que no momento da inferência. Ao tokenizar vários terabytes de texto para o corpus de treinamento, pode economizar tempo e custo, além de encurtar o ciclo de iteração ao ajustar datasets
Dedicar capacidade de engenharia para tornar 1.000 vezes mais rápida uma parte que representa 0,1% do tempo total de execução é exatamente o tipo de comportamento mais típico de desenvolvedor de software
https://x.com/mitchellh/status/2074225453217505494
LLMs estão muito mais perto do limite de melhorias de 1.000 vezes, mas é comum operações básicas do PyTorch serem 2 vezes mais lentas que uma simples reescrita, e algoritmos de escalonamento melhores às vezes trazem ganhos de 5 a 10 vezes. Tokenização rápida também pode abrir espaço para outras funcionalidades que até agora eram ignoradas por parecerem inviáveis
É um desempenho difícil de acreditar, a ponto de eu ter ficado um bom tempo olhando para os números do gráfico tentando entendê-los
É exatamente a funcionalidade de que o ClickHouse precisa, então pretendo testá-la em https://github.com/ClickHouse/ClickHouse/issues/108247
Seria bom se o README destacasse mais o desempenho por núcleo, e fico curioso se, no algoritmo real, correspondência com tabela hash perfeita ajudaria
Então fica a dúvida: quantas oportunidades de otimização de 1.000 vezes ainda restam em outras partes do pipeline de inferência?