Gigatoken (GitHub Repo)

TLDR AI 工具

摘要

Gigatoken 是一个即插即用的替代 tokenizer,声称相比 HuggingFace 的 tokenizer 速度提升高达 1000 倍,支持许多常见的 tokenizer 和 CPU。

Gigatoken 是一个用于语言建模的 tokenizer,支持广泛的 CPU 硬件以及几乎所有常用的 tokenizer。它可以通过自己的 API 使用,也可以以兼容模式与 Hugging Face Tokenizers 或 Tiktoken 一起使用。Gigatoken 比 Hugging Face 的 tokenizer 快大约 1000 倍,能够以每秒 GB 的速度对文本数据进行分词。
查看原文
查看缓存全文

缓存时间: 2026/07/22 21:30

marcelroed/gigatoken 来源: https://github.com/marcelroed/gigatoken

Gigatoken —— 比 HuggingFace 的 tokenizers 快约 1000 倍,可直接替换使用。

以 GB/s 的速率对文本数据进行分词!

GPT-2 加速比例

注意,HF tokenizers 和 tiktoken 本身已经是多线程 Rust 实现!

什么是 Gigatoken?

Gigatoken 是语言建模领域最快的分词器。它支持广泛的 CPU 硬件,以及几乎所有常用的分词器。详细吞吐量数据(按分词器和 CPU 分类)请参见 基准测试 部分。

安装

pip install gigatoken

使用

Gigatoken 可以与其自有 API 配合使用,也可以与 HuggingFace Tokenizers 或 Tiktoken 以兼容模式使用。

兼容模式(最简便)

import gigatoken as gt

# 对现有的 HuggingFace tokenizers 使用方式进行最小改动(兼容模式)
hf_tokenizer = ...
tokenizer = gt.Tokenizer(hf_tokenizer).as_hf()
# tokenizer 可以在与 hf_tokenizer 相同的上下文中使用
tokens = tokenizer.encode_batch(["This is a test string", "And here is another"])

# 或者配合 tiktoken
tiktokenizer = ...
tokenizer = gt.Tokenizer(tiktokenizer).as_tiktoken()
# 现在像现有的 tiktoken 分词器一样工作
tokens = tokenizer.encode_batch(["This is a test string", "And here is another"])

在此设置下,我们投入了大量精力确保输出与 HuggingFace Tokenizers 的结果完全一致,但这会对性能产生不可忽略的损失。即便如此,您仍然可以期望在所有情况下获得远高于原版的性能,但并非 Gigatoken API 可达到的 1000 倍。

Gigatoken API(最快)

import gigatoken as gt

tokenizer = gt.Tokenizer("Qwen/Qwen3-8B")  # 接受 HF 模型名称
file_source = gt.TextFileSource(["owt_train.txt"], separator=b"<|endoftext|>")
tokens = tokenizer.encode_files(file_source)

使用 Gigatoken API 可以让 Rust 实现直接读取数据,尽可能减少开销,同时允许最大限度的并行。请注意,通过此 API 传递 Python 数据结构仍会产生从 Python 读取的开销。

基准测试

在 owt_train.txt(11.9 GB)上的编码吞吐量 —— AMD EPYC 9565 72 核处理器 x 2 路(144 核)

分词器gigatokenHF tokenizerstiktokenvs HFvs tiktoken
GPT-224.53 GB/s24.8 MB/s36.0 MB/s989×681×
Phi-424.00 GB/s29.9 MB/s801×
GPT-OSS23.96 GB/s49.7 MB/s42.8 MB/s482×560×
OLMo 2 / 323.06 GB/s27.7 MB/s833×
Nemotron 322.79 GB/s49.4 MB/s462×
Qwen 322.16 GB/s34.2 MB/s648×
Llama 3 / 3.1 / 3.222.15 GB/s48.5 MB/s457×
GLM 520.97 GB/s74.8 MB/s280×
Llama 3.320.82 GB/s48.3 MB/s431×
Llama 420.77 GB/s72.7 MB/s286×
GLM 420.61 GB/s72.3 MB/s285×
Phi-4-mini20.05 GB/s27.6 MB/s726×
DeepSeek V3 / R1 / V419.69 GB/s26.2 MB/s750×
Qwen 2 / 2.519.12 GB/s27.7 MB/s691×
Kimi K218.85 GB/s
Qwen 3.5 / 3.615.49 GB/s27.7 MB/s558×
Gemma 44.82 GB/s334.1 MB/s14×
ModernBERT4.18 GB/s26.9 MB/s155×
Mistral 7B v0.33.57 GB/s354.7 MB/s10×
TinyLlama / Phi-3 (Llama 2)3.48 GB/s323.6 MB/s11×
CodeLlama3.47 GB/s347.4 MB/s10.0×
Gemma 33.43 GB/s357.2 MB/s9.6×
Gemma 12.51 GB/s342.2 MB/s7.3×

在 owt_train.txt(11.9 GB)上的编码吞吐量 —— Apple M4 Max(16 核)

分词器gigatokenHF tokenizerstiktokenvs HFvs tiktoken
GPT-28.79 GB/s6.9 MB/s62.8 MB/s1,268×140×
Nemotron 37.82 GB/s10.9 MB/s715×
Phi-47.76 GB/s7.7 MB/s1,012×
Llama 3 / 3.1 / 3.27.60 GB/s11.2 MB/s676×
OLMo 2 / 37.56 GB/s5.8 MB/s1,299×
Llama 3.37.50 GB/s15.7 MB/s479×
Phi-4-mini6.97 GB/s7.2 MB/s964×
Kimi K26.88 GB/s
Llama 46.81 GB/s11.6 MB/s590×
Qwen 2 / 2.56.37 GB/s5.8 MB/s1,105×
Qwen 36.36 GB/s6.9 MB/s918×
Qwen 3.5 / 3.66.31 GB/s6.3 MB/s994×
GPT-OSS6.20 GB/s20.2 MB/s87.2 MB/s306×71×
GLM 46.17 GB/s15.8 MB/s392×
DeepSeek V3 / R1 / V45.68 GB/s7.2 MB/s788×
GLM 55.55 GB/s12.2 MB/s456×
ModernBERT2.64 GB/s5.8 MB/s452×
Mistral 7B v0.31.99 GB/s95.1 MB/s21×
Gemma 41.82 GB/s85.2 MB/s21×
CodeLlama1.73 GB/s80.2 MB/s22×
TinyLlama / Phi-3 (Llama 2)1.69 GB/s80.1 MB/s21×
Gemma 11.42 GB/s85.7 MB/s17×
Gemma 31.38 GB/s82.2 MB/s17×

在 owt_train.txt(11.9 GB)上的编码吞吐量 —— AMD Ryzen 7 9800X3D 8 核处理器(16 核)

分词器gigatokenHF tokenizerstiktokenvs HFvs tiktoken
GPT-26.27 GB/s59.0 MB/s92.1 MB/s106×68×
Phi-46.09 GB/s55.4 MB/s110×
OLMo 2 / 36.06 GB/s55.4 MB/s109×
Phi-4-mini5.80 GB/s54.6 MB/s106×
GPT-OSS5.68 GB/s79.6 MB/s112.7 MB/s71×50×
Qwen 35.34 GB/s54.4 MB/s98×
Qwen 2 / 2.55.30 GB/s51.7 MB/s103×
Llama 3.35.26 GB/s79.9 MB/s66×
Llama 3 / 3.1 / 3.25.24 GB/s79.5 MB/s66×
Kimi K25.23 GB/s
Qwen 3.5 / 3.65.22 GB/s51.6 MB/s101×
Nemotron 35.20 GB/s79.0 MB/s66×
GLM 55.05 GB/s79.5 MB/s63×
GLM 45.04 GB/s79.5 MB/s63×
Llama 45.03 GB/s78.2 MB/s64×
DeepSeek V3 / R1 / V44.21 GB/s51.6 MB/s82×
ModernBERT2.84 GB/s52.1 MB/s54×
Mistral 7B v0.31.47 GB/s91.6 MB/s16×
Gemma 41.45 GB/s78.8 MB/s18×
CodeLlama1.38 GB/s85.2 MB/s16×
TinyLlama / Phi-3 (Llama 2)1.37 GB/s84.9 MB/s16×
Gemma 11.14 GB/s84.9 MB/s13×
Gemma 31.12 GB/s83.0 MB/s13×

基准测试详情

选择 OWT(OpenWebText)是因为它大致代表了从 CommonCrawl 文档中提取后的文本。Gigatoken 对整个文件进行不分块编码,因此它需要完成更多工作(查找分块边界并自动并行化),而这在其他分词器中是不存在的。

HuggingFace tokenizers(encode_batch_fast)处理前 100 MB,tiktoken(encode_ordinary_batch)处理前 1 GB,两者均已按 <|endoftext|> 预分块。这样做是公平的,因为所比较的分词器都不进行缓存,因此速度在整个处理过程中大致均匀。

Tiktoken 的行目前仅对获得官方支持的分词器填写。

速度最慢的行是基于 SentencePiece 的分词器,它们在 Gigatoken 中优化不足。

每行对应一个独特的分词器(相同的 vocabulary/merges/pretokenizer),在代表性仓库上测量。如果您未在此处看到您的分词器,它很可能基于某个现有分词器。例如:

  • Llama 3 / 3.1 / 3.2 — Llama 3 / 3.1 / 3.2, DeepSeek-R1-Distill-Llama, Hermes 3, Saiga 及其他 Llama-3 微调模型
  • Llama 3.3 — Llama 3.3, Llama-3.1-Nemotron-Nano-VL, SmolLM3, Kanana 1.5, jina-embeddings-v5, Ultravox
  • Qwen 2 / 2.5 — Qwen 2 和 2.5(包括 Coder 和 VL), Qwen3-Coder, Qwen3-VL, DeepSeek-R1 Qwen distills, MiMo V2.5, MiniCPM-o 2.6, InternVL3
  • Qwen 3 — Qwen 3(包括 Embedding 和 Reranker), Qwen2.5-Omni, Qwen3-VL-Embedding, MiMo V2.5 Pro, jina-reranker-m0, pplx-embed, MOSS-TTS, Zeta
  • DeepSeek V3 / R1 / V4 — DeepSeek V3 / V3.1 / V3.2, R1, V4 Flash 和 Pro, DeepSeek-VL2
  • GLM 4 — GLM 4.1V, 4.5, 和 4.7
  • GLM 5 — GLM 5 / 5.2 和 GLM-4.7-Flash
  • Nemotron 3 — Nemotron 3 Nano, Super, 和 Ultra
  • Kimi K2 — Kimi K2 / K2.5 / K2.6 / K2.7, Kimi-Linear, Kimi-VL, Moonlight
  • Phi-4-mini — Phi-4-mini 和 Phi-4-multimodal
  • TinyLlama / Phi-3 (Llama 2) — TinyLlama, Phi-3-mini, Phi-3.5-mini 和 Phi-3.5-vision(使用 Llama 2 vocabulary)
  • Gemma 3 — Gemma 3(270M–27B)和 EmbeddingGemma
  • Gemma 4 — Gemma 4(dense, MoE, 和 E-series)和 DiffusionGemma

常见问题

问:你们只是对某个特定 CPU 和分词器过度优化了吧?怎么会这么快?

不,我对所有这些组合都进行了过度优化!结果在不同 CPU(现代 x86 和 ARM)以及特定分词器上非常一致。主要的改进在于:使用 SIMD 对通常委托给正则表达式引擎的实现(预分词)进行重度优化,最小化分支和其他技巧,同时大量优化预分词映射的缓存(如果一个单词之前出现过,则高效查找其编码后的 token)。在这一领域,缓存是一个非常困难的问题,因为缓存增长非常快,并且预分词分布呈现出很长的尾部分布。其他的一些性能提升来自最小化与 Python 的交互以及避免线程间通信。

问:如何快速检查我的分词器是否受支持?

您无需安装任何东西即可尝试!以下命令将验证给定 HuggingFace 模型仓库的分词并计时:

# 下载您的数据
wget https://huggingface.co/datasets/stanford-cs336/owt-sample/resolve/main/owt_train.txt.gz
# 仅为示例!
gunzip owt_train.txt.gz
uvx --with tokenizers gigatoken bench 'openai-community/gpt2' owt_train.txt \
    --validate --doc-separator "<|endoftext|>"
cpu: Apple M4 Max, 16 cores
gigatoken: 1.432 s | 11920.51 MB at 8327.05 MB/s | 2701.65 Mtok at 1887.23 Mtok/s
hf: 16.250 s | 100.00 MB at 6.15 MB/s | 22.76 Mtok at 1.40 Mtok/s
gigatoken is 1353.13x faster than hf
validation OK: 20401 documents match
cpu: AMD EPYC 9565 72-Core Processor, 144 cores, 2 sockets
gigatoken: 0.486 s | 11920.51 MB at 24532.45 MB/s | 2701.65 Mtok at 5564.94 Mtok/s
hf: 4.033 s | 100.00 MB at 24.80 MB/s | 22.76 Mtok at 5.63 Mtok/s
gigatoken is 989.21x faster than hf
validation OK: 20401 documents match

以 EPYC CPU 上的速率来看,您可以在不到 6.5 小时内完成整个 Common Crawl(https://arxiv.org/pdf/2211.04325)的分词(通常被认为是整个互联网,130 万亿 token)!

此示例使用了该数据集(https://huggingface.co/datasets/stanford-cs336/owt-sample)的训练样本,CLI 默认截取文件的前 100MB 进行验证并与 HF 对比。您可以通过 uvx gigatoken bench --help 查看这些标志的帮助信息。

在 macOS 上可能需要运行两次命令才能获得良好的读数,因为第一次运行总会进行安全扫描,这会减慢 Rust 代码的速度。

问:我发现了不匹配/慢速的情况,这正常吗?

很可能不正常!尽管进行了相当广泛的测试,但我手头没有所有用例,请通过 GitHub Issue(https://github.com/marcelroed/gigatoken/issues)报告您发现的任何问题,以便我尽快解决。

引用

如果您在研究中使用 Gigatoken,请引用为:

@software{roed2026gigatoken,
  author = {Marcel R{\o}d},
  title = {{G}igatoken: SIMD and Cache Hierarchies for 1000x Faster Byte-Pair Encoding Tokenization on Modern CPUs},
  url = {https://github.com/marcelroed/gigatoken},
  year = {2026},
}

已知问题

  • Python 迭代在 Rust 中处理,但使用了 ABI3,这比使用内部版本特定的 CPython API 要慢。未来我打算针对每个 Python 版本进行专门优化以减少此开销。早期实验显示,在开销受限的情况下有 2 倍的改善。
  • Gigatoken API 中文件输出(file sinks)尚未实现。
  • WordPiece 尚未支持。
  • 基于 SentencePiece 的分词优化程度远不如更常见的 BPE 分词器。目前优先级较低,因为大多数是 Google 模型/BERT 风格模型使用 SentencePiece。
  • Windows 尚未经过充分测试,因此目前建议使用 WSL。

AI 使用声明

本代码库的大部分内容均为手动编写,未使用任何 AI(可从项目的 Git 历史中看出)。在项目的最后阶段,AI 被用于辅助:

  • 实现用户面向的 API
  • 扩展兼容性,例如泛化和移植预分词器实现以支持更多分词器,以及一些不引人注目的特性,如填充/截断/Unicode 归一化
  • 在 AVX512/AVX2/NEON 之间移植 SIMD 策略
  • 最终性能分析阶段,以及通过消除分支和改善预分词缓存层次结构获得的最后约 4 倍性能提升
  • 重构和代码复用

相似文章