La tokenización es la única parte del conjunto de modelos de lenguaje que casi nadie perfila. Gigatoken, publicado por Marcel Rød (un estudiante de doctorado de Stanford) bajo una licencia del MIT, sostiene que esto fue un error. La biblioteca codifica texto a gigabytes por segundo en una sola máquina, frente a líneas de base que ya son multiproceso de Rust.
La evaluación comparativa del tokenizador GPT-2 arroja resultados notables: evaluado en el corpus owt_train.txt de 11,9 GB utilizando una configuración de doble socket AMD EPYC 9565 de 144 núcleos, Gigatoken procesa datos a una asombrosa velocidad de 24,53 GB/s. En comparación, el tiktoken de OpenAI alcanza 36,0 MB/s, mientras que los tokenizadores HuggingFace registran 24,8 MB/s en la misma configuración de hardware. Estas marcas demuestran ventajas de rendimiento de 681x y 989x, respectivamente.
En un Apple M4 Max con 16 núcleos, la misma carga de trabajo GPT-2 se ejecuta a 8,79 GB/s, o tokenizadores HuggingFace 1268x y tiktoken 140x. En un AMD Ryzen 7 9800X3D de consumo, funciona a 6,27 GB/s, o 106x y 68x. La aceleración no es un artefacto de una CPU o un vocabulario.
¿Qué es GigaToken?
Gigatoken es un tokenizador de codificación de pares de bytes (BPE) escrito en Rust con enlaces de Python. Se envía en PyPI como gigatoken (versión 0.9.0, lanzada el 21 de julio de 2026) y se instala con pip install gigatoken. El repositorio es 66,2% Rust y 33,3% Python. Admite 23 familias de tokenizadores distintas en los puntos de referencia publicados, que cubren GPT-2, GPT-OSS, Llama 3 a 4, Qwen 2 a 3.6, DeepSeek V3/R1/V4, GLM 4 y 5, Kimi K2, Nemotron 3, Phi-4, OLMo 2/3, ModernBERT, Gemma y Mistral.
Hay dos formas de utilizarlo. El modo de compatibilidad envuelve un tokenizador HuggingFace o tiktoken existente y preserva la paridad de salida exacta, con un costo real de rendimiento. El autor (Marcel) afirma en Hacker News que el modo de compatibilidad ofrece aproximadamente 200 a 300 veces según el uso, porque todavía paga los gastos generales de Python por la creación de listas y la conversión de cadenas a bytes. La API nativa de Gigatoken permite a Rust leer archivos directamente y es de donde provienen los números publicados.
El explorador de referencia interactivo
Cada número a continuación se extrae de la sección de puntos de referencia del repositorio y del registro de optimización del pretokenizer. Cambie de CPU, recorra el historial de optimización o calcule cuánto tiempo tardaría su propio corpus.
'; PERF.forEach(funciones){ h += '
'+s[0]+'
'+s[1]+ (s[3]==='malo'?' no mantenido ':' mantenido ')+' ' + '[3]==='malo'?'" malo="">'+s[2].toLocaleString()+' MiB/s
' + barra(s)[2],max,s[3]==='malo') + '
'+s[4]+'
'; }); h+= '
Resultado neto: 2,27 × sobre la línea base winnow + NEON, 22,3 × sobre la implementación de expresiones regulares.
'; devolver h; } función fmt(seg){ if(seg < 1) return (seg*1000).toFixed(0)+' ms'; if(sec < 90) return sec.toFixed(1)+' s'; if(seg < 5400) return (seg/60).toFixed(1)+' min'; if(seg < 172800) return (seg/3600).toFixed(1)+' horas'; return (sec/86400).toFixed(1)+'días'; } función renderCalc(){ var opts=""; Object.keys(DATA).forEach(function(k){ opta += ''+DATA[k].label+''; }); devolver '
CPU'+opciones+'
' + '
Tokenizador
' + '
Tamaño del cuerpo: 1000 GB' + '
' + '
' + '
Extrapolación lineal del rendimiento medido anteriormente. Se supone que la tasa informada se mantiene ' + 'para todo el corpus, una sola máquina, sin límite de E/S. Las canalizaciones reales suelen estar vinculadas al almacenamiento antes de estar vinculadas al tokenizador. ' + 'Para escala: el archivo README de gigatoken señala que a tasas EPYC se podrían tokenizar todos los Common Crawl (' + 'aproximadamente 130 billones de tokens) en poco menos de 6,5 horas.
'; } función calcUpdate(){ var cpu = R.querySelector('#gt-cpu').value; var idx = parseInt(R.querySelector('#gt-tok').value,10); var gb = parseInt(R.querySelector('#gt-sz').value,10); R.querySelector('#gt-szv').textContent = gb.toLocaleString(); var fila = DATOS[cpu].filas[idx]; var tg = gb / fila[1]; varh="
gigatoken
"+fmt(tg) + '
en '+fila[1].toFixed(2)+' GB/s
'; si (fila[2]!== nulo){ var th = (gb*1000) / fila[2]; h+='
Tokenizadores HF
'+fmt(th) + '
en '+fila[2].toFixed(1)+' MB/s
'; h+='
Tiempo ahorrado
'+fmt(th-tg) + '
'+fila[4]+'× aceleración
'; } más { h += '
Tokenizadores HF
—
' + '
no reportado para este tokenizador
'; } si (fila[3]!== nulo){ var tt = (gb*1000) / fila[3]; h+='
tik token
'+fmt(tt) + '
en '+fila[3].toFixed(1)+' MB/s
'; } R.querySelector('#gt-res').innerHTML = h; } función fillTok(){ var cpu = R.querySelector('#gt-cpu').value, sel = R.querySelector('#gt-tok'), h=""; DATOS[cpu].rows.forEach(función(r,i){ h += ''+r[0]+''; }); sel.innerHTML = h; } var USO = '
Instalar
' + 'pip instala gigatoken' + '
Modo de compatibilidad: directo, aproximadamente 200 a 300 × según el autor
' + ' importar gigatoken como gtnn' + ' # Cambio mínimo respecto al uso de tokenizadores HuggingFace existentes n' + 'hf_tokenizer = …ntokenizer = gt.Tokenizer(hf_tokenizer).as_hf()nn' + 'tokens = tokenizer.encode_batch([ "Esta es una cadena de prueba" , "Y aquí hay otra" ])nn' + ' # O con tiktoken ntiktokenizer = …ntokenizer = gt.Tokenizer(tiktokenizer).as_tiktoken()' + '
API de Gigatoken: ruta más rápida, Rust lee los archivos directamente
' + ' importar gigatoken como gtnn' + 'tokenizer = gt.Tokenizer( "Qwen/Qwen3-8B" ) # acepta nombres de modelos HF n' + 'file_source = gt.TextFileSource([ "owt_train.txt" ], separator=b "<|endoftext|>" )n' + 'tokens = tokenizer.encode_files(archivo_fuente)' + '
Comprueba tu propio tokenizador sin instalar nada
' + 'uvx –con tokenizadores gigatoken bench 'openai-community/gpt2' owt_train.txt \n' + ' –validate –doc-separator "<|endoftext|>" ' + '
El subcomando de referencia valida la salida con los tokenizadores HuggingFace e imprime una comparación de tiempos. ' + 'En macOS, ejecútelo dos veces: la primera ejecución activa un análisis de seguridad que ralentiza el código Rust.
'; var LÍMITES = '
Problemas conocidos, declarados por el autor.
' + 'Wordpiece aún no es compatible. Los modelos Wordpiece de la familia BERT están fuera de alcance por ahora.' + 'SentencePiece está optimizado sólo parcialmente. Los vocabularios de Gemma, Mistral, CodeLlama y Llama 2 se encuentran en la banda de 7 a 22 ×, no en la banda de 1000 ×. + 'Los receptores de archivos no están implementados en la API de Gigatoken.' + 'La iteración de Python utiliza ABI3, que es más lenta que las API de CPython específicas de la versión. Los primeros experimentos muestran una ganancia del doble en los casos con sobrecarga. + 'Windows apenas se ha probado. El autor recomienda WSL por ahora.' + 'El modo de compatibilidad cuesta rendimiento. Se conserva la paridad de salida exacta con los tokenizadores HuggingFace, pero no la aceleración completa. + '
Uso declarado de IA
' + 'El autor afirma que la mayor parte del código fue escrito a mano y que la IA ayudó con la API orientada al usuario, ampliando la compatibilidad, ' + 'portando estrategias SIMD entre AVX512/AVX2/NEON, las etapas finales de creación de perfiles y aproximadamente los últimos 4x de rendimiento, y refactorización.' + '
Licencia y embalaje
' + 'Con licencia del MIT. Rust 66,2% / Python 33,3% por participación de lenguaje del repositorio. Publicado en PyPI como gigatoken.' + ''; var CMDS = { epyc:{línea:'banco gigatoken –cpu epyc-9565', get:function(){return renderBench('epyc');}}, m4:{línea:'banco gigatoken –cpu m4-max', get:function(){return renderBench('m4');}}, ryzen:{línea:'banco gigatoken –cpu ryzen-9800x3d', get:function(){return renderBench('ryzen');}}, perf:{line:'gigatoken perf –log pretokenizer', get:renderPerf}, calc:{line:'gigatoken estimación –corpus', get:renderCalc}, uso:{line:'gigatoken install –show-usage', get:function(){return USAGE;}}, límites:{línea:'límites de gigatoken', get:function(){return LIMITS;}} }; función mostrar(v){ var c = CMDS[v]; si(!c) regresa; LINE.textContent = c.line; CUERPO.innerHTML = c.get(); R.querySelectorAll('.gt-cmd').forEach(function(b){ b.setAttribute('aria-selected', b.dataset.v === v ? 'true' : 'false'); }); if(v === 'calc'){ fillTok(); calcUpdate(); R.querySelector('#gt-cpu').addEventListener('cambiar', function(){ fillTok(); calcUpdate(); }); R.querySelector('#gt-tok').addEventListener('cambiar', calcUpdate); R.querySelector('#gt-sz').addEventListener('input', calcUpdate); } cambiar tamaño(); } R.querySelectorAll('.gt-cmd').forEach(function(b){ b.addEventListener('click', function(){ show(b.dataset.v); }); }); función cambiar tamaño(){ probar{ if(window.parent!== ventana){ ventana.parent.postMessage({gigatokenHeight: R.offsetHeight + 40}, '*'); } }catch(e){} } window.addEventListener('resize', redimensionar); mostrar('epyc'); })();