LLMの前処理でテキストをトークン列に変換するトークナイザーは、長らく「Rustで書かれているのだから、もう十分速い」と思われてきた部品でした。そこへ2026年7月、HuggingFace tokenizers比で約1000倍を名乗るRust実装 gigatoken が公開され、Hacker Newsで613ポイント・119コメントを集めています。ただし「1000倍」は投稿タイトルの主張です。この記事では公式READMEの実測表と作者本人の補足を突き合わせ、どの条件で何倍出るのか、そしてそれが自分の用途で意味を持つのかを切り分けます。
- ・正体:Marcel Rød氏が単独開発するRust製のトークナイザー実装。★約3,119・MIT・コミット358件がすべて1人の手による
- ・何ができる:BPEトークナイズをGB/s級で実行。公式実測ではEPYC 144コアで24.53 GB/s、Apple M4 Maxで8.79 GB/s
- ・何を代替できる:HuggingFace tokenizers / tiktoken を互換モードで差し替え可能(
as_hf()/as_tiktoken()) - ・倍率の実際:GPT-2の対HF倍率は機体により106倍〜1,268倍。SentencePiece系では7〜22倍に落ちる
- ・注意:GitHub Releaseは0件(PyPIは0.9.0)。WordPiece未対応、Windowsは検証が薄くWSL推奨
この記事はLLMの前処理を担うトークナイザーの高速化実装として gigatoken を扱います。LLMそのものの仕組みや周辺技術の全体像は LLMとは?仕組み・主要モデル比較・ローカル実行・量子化を一気にまとめる2026年版 をご覧ください。
gigatokenとは:トークナイザーをGB/sで動かすRust実装
gigatokenは、LLMの学習・推論に入る前段でテキストをトークンIDの列に変換する処理だけを担う、単機能のライブラリです。GitHub APIで実体を確認すると、2026年7月25日時点で以下の状態でした。
| 項目 | 実測値(2026-07-25時点) |
|---|---|
| リポジトリ | marcelroed/gigatoken |
| スター数 | 3,119 |
| フォーク | 139 |
| ライセンス | MIT |
| 主要言語 | Rust |
| 初回コミット(リポジトリ作成) | 2025-11-10 |
| 最終push | 2026-07-23 |
| コントリビューター | 1名(marcelroed・358コミット) |
| GitHub Release / タグ | 0件 / 0件 |
| PyPI最新版 | 0.9.0(配布バージョンは0.3.0〜0.9.0の10種) |
| Open Issues | 13件 |
注目したいのはGitHubのReleaseもタグも0件である一方、PyPIには0.3.0から0.9.0まで10バージョンが並んでいる点です。バージョン管理はPyPI側だけで進んでおり、GitHub上の「安定版はどれか」という手がかりはありません。バージョン0.9.0という番号が示すとおり、1.0前の実装として扱うのが妥当です。
導入自体はPythonパッケージ1つで完結します。abi3ホイールがmacOS(x86_64 / arm64)・Linux(x86_64 / aarch64)・Windows(amd64 / arm64)向けに用意されており、Python 3.10以降が要件です。
pip install gigatoken
使い方は2系統に分かれます。ひとつはHuggingFace tokenizersやtiktokenと同じ呼び出し方ができる互換モード、もうひとつはRust側にファイル読み込みごと任せる独自APIです。この2つで性能が変わることが、後述する倍率の話に直結します。
① 何ができる:テキストのトークナイズをGB/s級で実行する。② 何を解決する:数GB〜数TBのコーパスをトークン化する工程が数時間〜数日かかる問題。③ 何を代替できる:HuggingFace tokenizers / tiktoken を互換モードで置き換えられる(ただし倍率は独自APIより落ちる)。
同じ「トークン化」でも、RAGの文脈で語られるチャンク分割とは対象が異なります。文書を意味のまとまりで区切る話は Chonkieとは?RAGチャンキングライブラリ 側の領域で、gigatokenが扱うのはその手前、バイト列を語彙IDに落とす処理です。
「1000倍」はどこまで本当か:実測表を3機体で読む
READMEには3種類のCPUでの実測表が掲載されています。ここが本記事の中心です。同じGPT-2トークナイザー・同じデータ(owt_train.txt 11.9GB)でも、倍率は機体によって1桁変わります。
数値を並べると次のようになります。
| 機体 | gigatoken | HF tokenizers | tiktoken | 対HF倍率 |
|---|---|---|---|---|
| AMD EPYC 9565 ×2ソケット(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 Ryzen 7 9800X3D(16コア) | 6.27 GB/s | 59.0 MB/s | 92.1 MB/s | 106× |
倍率が最大になるのは「比較相手が最も遅い機体」
表を縦に読むと、奇妙な事実が浮かびます。HuggingFace tokenizers側の数値がコア数にまったく比例していないのです。144コアのEPYCで24.8 MB/s、16コアのRyzenで59.0 MB/s——コア数が9倍の機体で、比較対象は逆に遅くなっています。gigatoken側は24.53 GB/s対6.27 GB/sと素直にスケールしているため、倍率の大きさは主にHF側がどれだけ振るわなかったかで決まっている構図です。
したがって「1000倍」という数字は、gigatokenが速いことと、比較対象が多コア環境でスケールしないことの積として現れています。手元が一般的な8〜16コアのデスクトップなら、READMEの実測表そのものが106倍という数字を提示している、と読むのが正確です。106倍でも十分に大きな改善ですが、桁がひとつ違います。
ベンチマーク条件の非対称性も押さえておく
READMEの「Benchmark details」には、3者が同じ作業をしているわけではないことが明記されています。gigatokenは11.9GBのファイルを分割せずそのまま読み、文書境界の探索と並列化まで自前で行います。対してHuggingFace tokenizersは先頭100MB、tiktokenは先頭1GBを、あらかじめ <|endoftext|> で分割した状態で受け取ります。
READMEはこれを「どちらもキャッシュを行わないため処理速度は全体を通じてほぼ一様であり、この比較は妥当」と説明しています。データ量の差そのものは合理的な説明がついている一方、gigatokenだけが分割処理も引き受けている点は、単純なライブラリ間比較ではなく「パイプライン全体としての比較」に近いことを意味します。有利にも不利にも働きうる条件差として認識しておくと、数字の読み方を誤りません。
トークナイザーの方式でも1桁変わる
機体差に加えて、どのトークナイザーを使うかでも効きが大きく変わります。EPYC機での実測表を方式別に並べると、傾向は明確です。
| トークナイザー | 方式 | gigatoken | 対HF倍率 |
|---|---|---|---|
| GPT-2 | BPE | 24.53 GB/s | 989× |
| Phi-4 | BPE | 24.00 GB/s | 801× |
| DeepSeek V3 / R1 / V4 | BPE | 19.69 GB/s | 750× |
| Qwen 3 | BPE | 22.16 GB/s | 648× |
| Llama 3 / 3.1 / 3.2 | BPE | 22.15 GB/s | 457× |
| Gemma 4 | SentencePiece系 | 4.82 GB/s | 14× |
| Mistral 7B v0.3 | SentencePiece系 | 3.57 GB/s | 10× |
| CodeLlama | SentencePiece系 | 3.47 GB/s | 10.0× |
| Gemma 3 | SentencePiece系 | 3.43 GB/s | 9.6× |
READMEはこの差の理由を「最も遅い行はSentencePieceベースのトークナイザーで、gigatokenでは十分に最適化されていない」と自ら記載しています。Known Issuesでも「主にGoogle系モデルやBERT系がSentencePieceを使うため優先度は低い」と位置づけられています。Gemma・Mistral・Llama 2系を主に扱っているなら、期待値は3桁ではなく1桁台に置くのが妥当です。
自分が使っているモデルが表に無い場合
実測表の各行は「同一の語彙・マージ規則・前分割器を持つ1種類のトークナイザー」を表しており、代表的なリポジトリで計測されています。READMEは「表に自分のトークナイザーが見当たらなければ、既存のどれかをベースにしている可能性が高い」として、主要な行がカバーする範囲を列挙しています。
| 表の行 | 同じトークナイザーを使う主なモデル |
|---|---|
| Llama 3 / 3.1 / 3.2 | Llama 3系のほか、DeepSeek-R1-Distill-Llama、Hermes 3、Saigaなどのファインチューン |
| 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蒸留版、MiniCPM-o 2.6、InternVL3 |
| Qwen 3 | Qwen 3(Embedding・Reranker含む)、Qwen2.5-Omni、jina-reranker-m0、MOSS-TTS |
| DeepSeek V3 / R1 / V4 | DeepSeek V3 / V3.1 / V3.2、R1、V4 Flash・Pro、DeepSeek-VL2 |
| Kimi K2 | Kimi K2 / K2.5 / K2.6 / K2.7、Kimi-Linear、Kimi-VL、Moonlight |
| Gemma 3 | Gemma 3(270M〜27B)、EmbeddingGemma |
| TinyLlama / Phi-3 (Llama 2) | TinyLlama、Phi-3-mini、Phi-3.5-mini、Phi-3.5-vision |
埋め込みモデルやリランカー、マルチモーダル系も既存の語彙を流用しているケースが多いため、自分のモデル名が直接載っていなくても、ベースを辿れば該当する行が見つかる構造になっています。逆に言えば、ベースがSentencePiece系であれば、モデル名が新しくても倍率は1桁台の側に入ります。
なお同じ「トークナイザー」という語でも、音声合成の分野では離散トークンを介さない設計が模索されています。方向性の違いは VoxCPM2|トークナイザレス多言語TTS が扱う話題で、gigatokenは逆に既存のトークナイズ処理そのものを速くする立場です。
なぜ速いのか:正規表現をSIMDに置き換え、pretokenキャッシュを積む
作者はREADMEのFAQで、速度の出どころを2つ挙げています。ひとつはpretokenization(前分割)の自前実装、もうひとつはpretokenのキャッシュです。
前提として押さえておきたいのは、比較対象がPython実装ではないことです。READMEは図の直下で「HF tokenizersもtiktokenも、すでにマルチスレッドのRustで動いている」とわざわざ注記しています。つまりこの3桁の差は「PythonをRustで書き直した」類の改善ではなく、同じRust・同じマルチスレッド前提のうえで積まれた差ということになります。ここを取り違えると、速度の出どころを見誤ります。
BPEトークナイザーは通常、まずテキストを単語やその断片へ切り分け(pretokenize)、次にそれぞれをマージ規則に沿ってトークンIDへ変換します。前段の切り分けはほとんどの実装で正規表現エンジンに任されており、作者はここが実質的なボトルネックだったと述べています。gigatokenはこの部分を、分岐を減らしたSIMD実装で置き換えました。
後段については、一度見た単語のトークン列を引き直すキャッシュを積んでいます。作者はこれを「この領域ではキャッシュが非常に難しい問題」だと補足しており、理由としてキャッシュが急速に肥大化することと、pretokenの分布が極端にロングテールであることを挙げています。加えて、Pythonとのやり取りを最小化し、スレッド間通信を避けたことも寄与しているとしています。
これらの説明は、リポジトリの構成からも裏づけが取れます。src/pretokenize/reference/ にはSIMD実装(simd.rs 約28KB)とAVX512向け実装(avx512.rs 約16KB)、状態機械(state_machine.rs)が置かれ、src/bpe/pretoken_cache.rs は約21KBあります。さらに src/pretokenize/fast/ 配下には cl100k.rs / o200k.rs / qwen2.rs / qwen3_5.rs / deepseek_v3.rs / kimi.rs / nemotron.rs / olmo3.rs / r50k.rs と、語彙ファミリーごとの個別実装が並びます。「あらゆる組み合わせに対して過剰に最適化した」というFAQの表現は、ファイル構成と整合しています。
owt_train.txt など"] --> B["pretokenize
単語・断片へ切り分け"] B --> C{"gigatokenは
ここを置換"} C -->|従来| D["正規表現エンジンに委譲
実質的なボトルネック"] C -->|gigatoken| E["SIMDの自前実装
AVX512 / AVX2 / NEON"] D --> F["BPEマージ規則を適用"] E --> G{"pretokenキャッシュ
に既出か?"} G -->|ヒット| H["トークン列を引き直す"] G -->|ミス| F F --> I["トークンID列を出力"] H --> I
READMEには「AI Use Disclosure」も置かれています。コードベースの大部分はAIを使わず手作業で書いたとしたうえで、最終段階では利用者向けAPIの実装、対応トークナイザーの拡張、AVX512・AVX2・NEON間でのSIMD戦略の移植、そして分岐削減とキャッシュ階層の改善による最後の約4倍分の性能向上に補助として使ったと明記されています。速度の大部分が人手の設計に由来し、仕上げにAIを使ったという整理です。
自分の環境でトークナイザーのベンチを再現する
READMEで最も実用的なのは、インストールなしでベンチマークを実行できるコマンドが用意されている点です。手元の機体がどの倍率帯に入るのかは、実測表を眺めるより自分で回したほうが早く分かります。
まず比較用のデータを取得します。READMEが例示しているのは、Stanford CS336の講義で使われるOpenWebTextのサンプルです。
wget https://huggingface.co/datasets/stanford-cs336/owt-sample/resolve/main/owt_train.txt.gz
gunzip owt_train.txt.gz
続いてベンチマークを実行します。uvx 経由なので pip install は不要です。--validate を付けると、HuggingFace tokenizersと出力が一致するかの検証まで行われます。
uvx --with tokenizers gigatoken bench 'openai-community/gpt2' owt_train.txt \
--validate --doc-separator "<|endoftext|>"
READMEに掲載されている実行結果は次のような形式です(M4 Maxの例)。処理時間、データ量、スループット、トークン数が並び、最後に倍率と検証結果が出ます。
・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
最後の行が重要です。20,401文書でトークン列が完全一致したという検証結果があるため、「速いが結果が違う」という疑いは、少なくともこの構成では否定されています。速度の主張と正しさの主張が同じコマンドで同時に確認できる設計は、ベンチマークの信頼性を判断するうえで評価できる点です。
・CLIは既定で、検証とHF比較のためにファイル先頭100MBに絞る。フラグは
uvx gigatoken bench --help で確認できる・macOSでは初回実行時にセキュリティスキャンが走りRust側が遅くなるため、2回実行して2回目の値を読む
・上記のREADME掲載値は1,353倍だが、同じM4 Maxでも実測表側は1,268倍。同一機体でも実行ごとにぶれる前提で読む
なお本記事では、記載されている数値の出典確認(GitHub API・PyPI・リポジトリのファイル構成)までを行い、ベンチマークの実行そのものは行っていません。上記の数値はすべて公式READMEおよび作者の公開コメントに基づく引用値です。
どこに効くのか:事前学習データの前処理・TTFT・埋め込み
Hacker Newsのスレッドで最も多かった反応は、称賛ではなく「トークナイズは推論時間の0.1%未満ではないか」という疑問でした。この問いは正当で、答えは用途によって変わります。
作者自身が挙げた主用途は事前学習の実験です。データの配合・フィルタ・前処理を変えるたびにコーパス全体をトークン化し直す必要があり、DCLM規模のデータでは多数のCPUを使って数日走らせる工程になる、と説明しています。同様の指摘は他の参加者からも出ており、事前学習データはGPU時間を無駄にしないよう事前にトークン化しておくのが通例であるため、この工程の短縮は素直に効きます。学習データのトークン化に10〜15分待たされた末に軽微なバグで実行が落ちた、という経験談も投稿されていました。
スレッドには、推論以外の場面でトークナイズが実際に効いていたという報告も複数ありました。64Mパラメータ規模のBERT系分類モデルを使うシステムでは、システムの他の部分がGB/s級で処理できるのにトークナイズだけがMB/s級で足を引っ張り、モデル推論より安いはずのトークナイズが全体の実行時間の1割超を占めていたという例。検索のたびにメタデータを都度埋め込む構成で、トークナイズがCPU時間の99%以上を占めていたという例。AIプラットフォームを運用する立場からは、ルーティングやレート制限の判断を下すためにリクエストの早い段階で高速にトークン化する必要がある、という指摘も出ています。いずれも「推論全体に占める割合」ではなく「その処理系のなかでの割合」で見ると話が変わる、という構図です。
分析データベース側からの反応もあり、ClickHouseのリポジトリではgigatokenを取り込む方向のissueが立てられています。トークナイズを推論の前段としてではなく、データ処理そのものとして扱う文脈です。
推論側については、作者がTTFT(最初のトークンが出るまでの時間)の計測値を公開しています。単一のB200上で8BのQwen3を動かした条件で、入力2048トークンのとき 30.74ms → 29.05ms、約5.5%の短縮でした。作者はモデルが小さくGPUが速いほど効果が大きくなるとも述べています。1000倍という入口の数字に対し、推論の体感に効く幅は数%というのが実測の姿です。
| 用途 | 効き方 | 根拠 |
|---|---|---|
| 事前学習データの前処理 | 大きい | 作者の主用途。CPU群で数日回す工程 |
| 埋め込み・分類の大量バッチ | 大きい | 小型分類モデルではトークナイズが処理時間の1割超という報告 |
| 送信前のトークン数カウント | 中 | ルーティング・レート制限・バッチ分割の判断に使う |
| 推論のTTFT | 小(数%) | 入力2048トークンで約5.5%短縮(作者計測) |
| 推論の総時間 | ほぼ無し | 元々1%未満という指摘が最多 |
READMEはEPYC機の速度を根拠に、Common Crawl全体(インターネット全体に相当するとされる130兆トークン)を6.5時間弱でトークン化できるという試算も載せています。これは実行結果ではなく速度からの換算値ですが、この工程を担当する立場なら意味の分かる数字です。
独自APIを使う場合、Rust側にファイルを直接読ませることで往復のオーバーヘッドを避けられます。互換モードとの差はここで生まれます。
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)
ローカル環境でLLMを動かす際の律速がどこにあるかは、モデルサイズやランタイムによって変わります。手元の機材で何が動くかを先に確かめたい場合は llmfit完全ガイド:今のPCで動くローカルLLMを1コマンドで判定、Apple Silicon環境での推論サーバー構成は omlx徹底解説|Apple Silicon専用のローカルLLMサーバー が参考になります。
導入前の制約とライセンス
MITライセンスで公開されており、商用利用を含めて扱いやすい部類です。一方で、1.0前の実装らしい制約がREADMEのKnown Issuesに率直に並んでいます。
最も実務に響くのが互換モードの倍率です。READMEは、互換モードでは出力がHuggingFace tokenizersと厳密に一致するよう相当な労力を払った一方、それが性能面で無視できないコストになっていると説明し、「全般に大幅な高速化は期待できるが、独自APIで得られる1000倍には届かない」と明記しています。作者はスレッド上で、互換モードの目安を200〜300倍程度と述べています。既存コードをほぼ変えずに差し替える運用なら、この帯が現実的な期待値です。
・WordPiece未対応。BERT系の一部で使われる方式は現時点で対象外
・SentencePiece系は最適化が薄い。Gemma・Mistral・Llama 2系は1桁台の倍率
・Windowsは検証が薄い。READMEはWSLの利用を推奨(ホイール自体は配布されている)
・ファイルシンク未実装。独自API側で結果をファイルへ直接書き出す経路は未整備
・ABI3由来のオーバーヘッド。Python側の反復処理はバージョン特化していないぶん遅く、作者は将来的な特化で2倍程度の改善余地があると述べている
エコシステムはまだ形成の途中です。READMEには研究利用向けの引用形式(BibTeX)が置かれており、そのタイトルは「現代CPU上での1000倍高速なBPEトークナイズのためのSIMDとキャッシュ階層」と読める内容で、作者自身が技術的な主眼をこの2点に置いていることが分かります。Rustクレートは未公開で、作者は公開予定とAPI設計への意見募集を表明しています。技術的な解説記事・論文・発表動画も準備中とされています。一方で公開から数日でRuby移植(gigatoken-rb)が現れるなど、周辺の動きは早く進んでいます。GitHub Releaseが0件でバージョンの節目が読み取りにくい点と合わせ、本番投入するならPyPIのバージョンを固定し、--validate で出力一致を確認したうえで進めるのが安全です。
まとめ
「1000倍」は誇張ではないが、条件付きの上限値である。公式READMEは同じ表の中に989倍・1,268倍と並べて106倍も載せており、SentencePiece系では1桁台まで落ちることも自ら明記している。数字を割り引く必要はなく、自分の機体とトークナイザー方式がどの行に当たるかを読むのが正しい使い方だ。
効果が確実に出るのは、トークナイズがCPU時間の大半を占める工程——事前学習データの前処理、大量の埋め込み・分類バッチ、送信前のトークン数カウント。推論の総時間短縮を期待すると肩透かしになる(TTFTで約5.5%)。
判断に迷うなら、
uvx --with tokenizers gigatoken bench を --validate 付きで手元で1回回すのが最短だ。倍率と出力一致が同時に確認でき、READMEの表を信じるかどうかという議論を飛ばせる。
トークナイザーは長らく「最適化し尽くされた枯れた部品」と見なされてきました。gigatokenが示したのは、そう思われていた領域にも1人の手で3桁の余地が残っていたという事実です。その改善が自分の用途に効くかどうかは別の問いですが、少なくとも確かめる手段は用意されているという点で、扱いやすいプロジェクトだと言えます。
参照ソース
・marcelroed/gigatoken(公式リポジトリ・README) — 3機体の実測表・ベンチマーク条件・FAQ・Known Issues・AI Use Disclosure・引用形式
・Hacker News — GigaToken: ~1000x faster Language model tokenization — 作者本人によるTTFT計測値、互換モードの倍率目安(200〜300倍)、事前学習用途の説明、Rustクレート公開予定
・PyPI — gigatoken — 配布バージョン(0.3.0〜0.9.0)・対応プラットフォーム・Python要件
・GitHub API — marcelroed/gigatoken — スター数・ライセンス・コントリビューター数・Release/タグ件数の実測(2026-07-25取得)