alitrack

Rust Tokenizer跑出24GB/s——比HuggingFace快1000倍

Tokenization 从来不是 LLM 训练的瓶颈。至少大家是这么认为的。

GPU 吃掉了 99% 的训练时间,谁会在意 CPU 上的分词环节?HuggingFace 的 tokenizers 库是 Rust 写的,OpenAI 的 tiktoken 也是 Rust 写的——多线程,够快了。

直到有人真的 profile 了一下。

Marcel Rød,Stanford 三年级博士生,用 8 个月时间重写了 BPE tokenization 的核心路径。结果:GPT-2 的分词速度从 24.8 MB/s 飙到 24.53 GB/s——989 倍。在 AMD EPYC 9565(144 核)上,11.9 GB 的 OpenWebText 数据集只需 0.49 秒就能完成分词。按照这个速度,「整个 Common Crawl」(130 万亿 token)只需不到 6.5 小时。

项目叫 Gigatoken,Rust 实现,MIT 协议,2.9K stars。2026 年 7 月 22 日登上 Hacker News 首页。

● ● ●

为什么之前的 Tokenizer 这么慢?

不是正则引擎不够快,是把整个预分词都外包给了它。

HuggingFace 的 tokenizers 和 OpenAI 的 tiktoken 都依赖正则引擎来做预分词(pretokenization)——把文本切成一个个"词单元",然后对每个单元做 BPE 合并。正则引擎的问题在于:它是通用的模式匹配引擎,不知道自己在做什么。每次匹配都要走完整的状态机,而且是逐字节的。

Gigatoken 的做法完全不同。核心思路是三层管线:

Gigatoken架构

Gigatoken架构

1. SIMD 预分词取代正则引擎

不调 regex 库。直接手写 SIMD:

  • 一个 256 字节的查找表(LUT),看一眼首字节就知道这个 token 是字母/数字/空格/符号,O(1) 分发到对应的扫描函数
  • 扫描函数用 SWAR(SIMD Within A Register)技术——一个 u64 算术操作同时检查 8 个字节是否是字母((b | 0x20) - b'a' 的结果小于 26),比逐字节 + 分支快得多
  • AVX-512/NEON 批量分类:一次处理 64 字节,用 SIMD 比较指令生成掩码,然后提取边界位置

在 M4 Max 上,预分词这一个环节就从 ~47 MiB/s(fancy-regex)优化到了单线程 ~950 MiB/s。这是 20 倍的提升——在还没进入 BPE 合并之前。

2. 缓存层级:99.4% 的预分词不用重新计算

这是 Gigatoken 最巧妙的设计。

自然语言里绝大多数"词"是重复的——"the"、"and"、"of"在文本中反复出现。传统 tokenizer 每次遇到都要重新走一遍 BPE 合并。Gigatoken 在预分词和 BPE 合并之间插了一层缓存:

  • 一个自定义的开放寻址哈希表,2 MiB 大页对齐,64 MB 容量
  • 键是预分词的前 15 个字节直接打包到 u128(一次 pcmpeqb 比较),值是编码后的 token ID 序列
  • 表容量 64 MB 远超 L2/L3,所以用了两级预取管线——phase B 预取到 L2,emit 循环预取到 L1
  • 在 OpenWebText 上命中率 99.4%

这意味着一亿个词里,只有 60 万个真正需要走 BPE 合并。其余的直接从缓存表里查出结果,一次加载。

那 0.6% 的未命中怎么办?Gigatoken 也为这个路径做了极致优化。

3. PairRankTable:两级扁平化合并查找

BPE 合并的核心是一个查找操作:给定两个 token ID (a, b),它们能合并成什么?传统做法是用一个 HashMap,键为 (u32, u32) 对、值为 u32——每次查找两次哈希计算 + 探测。

Gigatoken 替换成了两层结构:

  • Dense 层
    :一个 2048×2048 的 16 MiB 网格,覆盖所有初始字节 token 对。合并循环里约一半的查找落在这一层——一个移位指令 + 一次 L3 加载,无哈希、无探测。
  • Flat 层
    :剩余合并对放在一个自定义开放寻址表中,每个槽 8 字节压缩((key, merged_id) 打包为一个 u64),一次乘法 + 一次加载 + 一次比较。因为负载因子不超过 50%,miss 通常停在第一个空槽。

再加上针对短序列的栈上双向链表合并(零堆分配),整个 miss 路径也被压缩到了极致。

● ● ●

实际有多快?

在 OpenWebText 11.9 GB 数据集上的编码吞吐(GPT-2 tokenizer):

平台
Gigatoken
HF tokenizers
tiktoken
vs HF
AMD EPYC 9565 (144核)
24.53 GB/s
24.8 MB/s
36.0 MB/s
989×
Apple M4 Max (16核)
8.79 GB/s
6.9 MB/s
62.8 MB/s
1,268×
AMD 9800X3D (8核)
6.27 GB/s
59.0 MB/s
92.1 MB/s
106×

注意:HF tokenizers 和 tiktoken 本身就是多线程 Rust。Gigatoken 快在算法,不是快在语言。

覆盖范围也远超预期——支持 30+ 种主流 tokenizer:GPT-2/4、Llama 3/4、Qwen 2-Qwen3.6、DeepSeek V3/R1/V4、GLM 4/5、Gemma 1-4、Phi-3/4、Kimi K2 等等。几乎涵盖所有常见模型。

● ● ●

集成到现有管线

Gigatoken 提供了三层接口:

最快:Gigatoken API

import gigatoken as gt tokenizer = gt.Tokenizer("Qwen/Qwen3-8B") tokens = tokenizer.encode_files(gt.TextFileSource(["data.txt"]))

Rust 直接 mmap 读文件,零 Python 开销,989 倍。

兼容模式:HF Tokenizers 替换

tokenizer = gt.Tokenizer(hf_tokenizer).as_hf() tokens = tokenizer.encode_batch(texts)  # 200-300× 快

一行代码切换,接口完全兼容。

tiktoken 替换

tokenizer = gt.Tokenizer(tiktokenizer).as_tiktoken()

还提供 CLI 快速验证:

uvx gigatoken bench 'openai-community/gpt2' data.txt --validate

● ● ●

这意味着什么?

Gigatoken 不是"又一个 tokenizer"——它刷新了我们对 tokenization 性能上限的认知。之前的共识是"tokenization 不是瓶颈,GPU 才是"。Gigatoken 证明:不是 tokenization 不够快,是从来没有人认真优化过它。

这有几个实际影响:

  1. 01训练数据预处理不再是瓶颈
    。当分词比下载数据还快的时候,预处理管线可以大幅简化。
  2. 02本地推理的数据预处理会受益
    。在边缘设备上,每一毫秒的 CPU 时间都很珍贵。
  3. 03DuckDB + tokenization 成为可能
    。把 Gigatoken 嵌入 DuckDB 扩展,文本数据的读取→清洗→分词可以在 SQL 里一个查询完成,无需 Python 往返(我们在做这个:duckdb_gigatoken)。

● ● ●

已知限制

  • SentencePiece 后端慢
    :Gemma、Mistral 等 SentencePiece tokenizer 只快了 10-20 倍(vs BPE 的 500-1000 倍)。作者说低优先级——主要用于 Google 系模型。
  • 单人项目
    :100% 提交来自 Marcel Rød。代码质量极高(profiling 文档是教科书级的),但 bus factor 是 1。
  • WordPiece 未实现
    、Windows 测试少、无 file sinks。

但这些不影响它的核心价值:证明了 tokenization 的上限远高于我们认为的水平。

● ● ●

技术细节值得一看

Gigatoken 的源码不仅是工业级的 SIMD 优化示范,还是性能剖析驱动开发的教科书。仓库里有两份深度分析报告:

  • profiling/report.md
    :M4 Max 单线程 10 GB OWT 的 samply + xctrace CPU Counters 分析——精确到每条热指令的微架构归因
  • profiling/zen5_st_profile.md
    :Zen 5 的 perf 冷/暖阶段分解——发现了一个 THP ordering bug(madvise 在 memset 之后调用,导致大页从未生效),修复后 +15.4%

每个优化都有 A/B 测试支持,每一步都精确测量。这种"先测量、再优化、后记录"的工程文化,比 Gigatoken 本身更值得学习。


Gigatoken 证明了:在 AI 基础设施里,没有哪个环节是"已经足够快"的。只是还没人认真量过。

试试 uvx gigatoken bench 'openai-community/gpt2' your_data.txt --validate,跑通的话告诉我你的加速比。

你之前留意过 tokenization 的性能吗?还是和我一样默认"这不是瓶颈"?