新闻宏观经济Gigatoken:基于Rust的BPE分词器,编码速度达24.53 GB/s,比HuggingFace Tokenizers快989倍

Gigatoken:基于Rust的BPE分词器,编码速度达24.53 GB/s,比HuggingFace Tokenizers快989倍

作者: MarkTechPost·

要点速览

  • Gigatoken 0.9.0是一个基于Rust的BPE分词器,带有Python绑定,在MIT许可下发布并可在PyPI上获取。
  • 在144核心AMD EPYC 9565系统上,Gigatoken以24.53 GB/s处理GPT-2工作负载,而tiktoken为36.0 MB/s,HuggingFace tokenizers为24.8 MB/s。
  • 该库的主要性能提升来自手写预分词器、基于SWAR的优化、双游标指令级并行、预分词缓存以及减少Python交互。
  • Gigatoken支持23种分词器系列,在x86和ARM系统上均表现优异,但SentencePiece的加速较低且不支持WordPiece。
  • KrabArena的独立复现发现,在4个vCPU的Intel Xeon虚拟机上,Gigatoken 0.9.0比tiktoken快26.2倍,比HuggingFace tokenizers快83.4倍。
Gigatoken:基于Rust的BPE分词器,编码速度达24.53 GB/s,比HuggingFace Tokenizers快989倍

分词——将原始文本转换为语言模型实际消费的数值标记序列的预处理步骤——仍然是机器学习技术栈中最少被性能分析的组件之一。随着训练数据集增长到太字节和拍字节级别,这一转换所花费的时间可能成为数据准备流程中的实际瓶颈,但它很少成为优化工作的焦点。Gigatoken是由斯坦福大学博士生Marcel Rød在MIT许可下发布的新库,它论证了这一疏忽是需要付出代价的。该库在单台机器上实现了每秒千兆字节的文本编码速度,超越了已经用多线程Rust实现的基准库。

基准测试结果

在使用11.9 GB owt_train.txt语料库、144核心AMD EPYC 9565双路系统上对GPT-2分词器进行的基准测试中,Gigatoken的数据处理速度达到24.53 GB/s。在相同硬件上,OpenAI的tiktoken——用于为GPT模型编码文本的库——速度为36.0 MB/s,HuggingFace tokenizers——开源机器学习生态系统中事实上的标准分词器——速度为24.8 MB/s,这意味着Gigatoken分别实现了681倍和989倍的性能优势。

加速效果在不同架构上保持一致。在16核心的Apple M4 Max上,相同的GPT-2工作负载以8.79 GB/s运行——比HuggingFace tokenizers快1,268倍,比tiktoken快140倍。在消费级AMD Ryzen 7 9800X3D上,Gigatoken达到6.27 GB/s,相对于各自基准实现了106倍和68倍的加速。

Gigatoken是什么

Gigatoken是一个用Rust编写的字节对编码(BPE)分词器,带有Python绑定。BPE是现代大语言模型主流的子词分词算法,被GPT、Llama、Qwen和Mistral等系列模型所使用。它在PyPI上以gigatoken发布(版本0.9.0,2026年7月21日发布),可通过pip install gigatoken安装。代码库中66.2%为Rust,33.3%为Python。其已发布的基准测试覆盖23种不同的分词器系列,包括GPT-2、GPT-OSS、Llama 3至4、Qwen 2至3.6、DeepSeek V3/R1/V4、GLM 4和5、Kimi K2、Nemotron 3、Phi-4、OLMo 2/3、ModernBERT、Gemma和Mistral。

Gigatoken提供两种使用模式。兼容模式封装现有的HuggingFace或tiktoken分词器,保持精确的输出一致性,但以吞吐量为代价。Rød在Hacker News上表示,兼容模式根据使用情况提供大约200–300倍的加速,因为它仍然承担列表创建和字符串转字节转换的Python开销。原生Gigatoken API允许Rust直接读取文件,是已发布基准数据的来源。

技术方法

性能提升并非来自更快的BPE合并循环,而是源于大多数分词器视为已解决的两个领域。

预分词优化

大多数实现将预分词委托给正则表达式引擎。Gigatoken手工编写了整个预分词器。预分词器优化日志跟踪了在100 MB OpenWebText上的单线程GPT-2预分词器吞吐量,揭示了详细的优化进展:

  • fancy-regex基线运行速度约为47 MiB/s。
  • 手写状态机达到约380 MiB/s。
  • 使用NEON SIMD内联函数的winnow组合子实现达到462 MiB/s。

进一步的优化来自于用直接迭代器替换winnow,添加256字节的类查找表以实现O(1)首字节分派,以及从NEON内联函数切换到SWAR(寄存器内SIMD)。SWAR将8个字节作为u64加载,并使用无分支算术检查全部8个字节的字母属性,无需特定架构的内联函数。这将吞吐量提升至830 MiB/s。

最后的优化步骤涉及双游标指令级并行(ILP)利用,达到1,049 MiB/s。关键洞察是约840 MiB/s处的瓶颈是延迟而非吞吐量。每个标记的结束位置取决于前一个标记,形成大约25–27个周期的串行链。通过从安全分割点运行两个独立的游标,乱序执行引擎可以在空闲执行端口上交织两个流。

仅预分词器的净效果:相对于winnow + NEON基线提升2.27倍,相对于正则表达式实现提升22.3倍。

预分词缓存

当一个词之前出现过时,其编码后的标记将被查找而非重新计算。Rød指出这在实践中很困难,因为缓存增长迅速,且预分词分布呈现长尾模式。此外,与Python的交互被最小化,线程被设计为彼此之间交互最少。

优化日志还记录了不起作用的方法。使用#[cold]#[inline(never)]的热/冷分离回退至580 MiB/s并被撤销,因为内联屏障阻止了LLM优化合并的ASCII和unicode循环。使用SWAR转换计数的两遍分类缓冲区在算法上是正确的,但运行速度为354 MiB/s,因为额外的内存流量抵消了分支节省。配置文件引导优化没有可测量的效果,因为内循环已经是无分支的,且词边界分支是数据相关的。

基准测试方法论

此比较并非严格意义上的同类对比。Gigatoken编码整个未分割的文件,自行查找文档边界并自动并行化。HuggingFace(encode_batch_fast)在前100 MB上进行评估,tiktoken(encode_ordinary_batch``)在前1 GB上进行评估,两者均在<|endoftext|>`上预分割。由于基准库未实现缓存,其吞吐量保持一致。所有测量报告使用启用并行性的新进程进行三轮交替测试中的最佳值。

词表类型也引入了限制。SentencePiece分词器仅部分优化。在EPYC上,Gemma 1以2.51 GB/s处理(7.3倍加速),Gemma 3以3.43 GB/s(9.6倍),CodeLlama以3.47 GB/s(10.0倍)。虽然这些增益相当可观,但比头条BPE性能数据低一个数量级。

KrabArena上的独立复现验证了结果。在4个vCPU的Intel Xeon虚拟机(2.20 GHz)上,使用174 MB的OpenWebText切片,Gigatoken 0.9.0实现了277.8 MB/s的中位数,比tiktoken 0.13.0(10.62 MB/s)快26.2倍,比tokenizers 0.23.1(3.33 MB/s)快83.4倍。所有试验成功验证了35,356个文档,证实性能趋势随核心数量扩展。

范围与局限性

Gigatoken的加速在x86和ARM架构以及全部23种支持的系列分词器上均成立,而非仅限于单一调优配置。然而,SentencePiece词表实现的加速为7–22倍而非1,000倍级别的增益,且不支持WordPiece。兼容模式以大约200–300倍的加速保持精确的HuggingFace输出一致性,而非完整的原生加速。

GitHub仓库基准测试浏览器均公开可用。