TL;DR: 0.1%、一成以上、九成以上,這是同一串討論裡三個人各自量到的 tokenization 佔比:一個看的是整段推論,一個做 64M 參數的小模型分類,一個每次搜尋都要當場算 embedding。Gigatoken 作者自己貼的推論端實測是平均 TTFT 改善 5.5% 到 8.4%,而他主要的用途是離線資料處理,那種工作要跑上好幾天。
tokenization 佔一個系統多少成本,答案的落差很大:有人量到不到總推論時間的 0.1%,也有人量到九成以上的 CPU 時間都花在這裡。這些說法出現在同一串討論底下,講的人各自在做不同的系統。
Tokenizer 是把文字切成 token 的那一套程式,token 本身是什麼可以參考Token 是什麼?LLM 為何只讀 Token?。這串討論來自 Gigatoken 這個 tokenizer 專案,作者 Marcel Rød 本人也在裡面回覆。討論串裡的數字多半是各自報上來的,Gigatoken 那組也還沒有第三方的重測。落差這麼大,是因為 tokenizer 在每個人的系統裡站的位置不一樣。
推論裡佔多少
有人留言說,tokenization 在整個推論時間裡通常不到 0.1%。作者接的是另一個窗口:TTFT 算的是從輸入送進去到模型吐出第一個 token 為止,中間包含把整段 prompt 讀完的 prefill,而 prefill 這一段每個 token 花掉的 GPU 時間比後面低很多,tokenization 在裡面的比重就跟著高起來。
他後來貼了一組實測:8B 的 Qwen3、單張 B200,輸入長度 2048 的時候,平均 TTFT 從 30.74 ms 降到 29.05 ms,大約 5.5%;8192 是 105.20 ms 降到 96.36 ms,8.4%;32768 是 687.05 ms 降到 633.66 ms,7.8%。他註明這些是初步數字,還要再測。一個看的是整段推論,一個看到第一個 token 為止,量的東西不同,數字自然對不起來。
小模型的情況
一位留言的人講了幾年前做過的分類系統:模型是 64M 參數的 BERT,系統其他部分每秒能處理幾 GB 的資料,tokenizer 只有每秒幾 MB,整條線就卡在這裡。他說模型推論比 tokenization 貴,但 tokenization 還是佔掉「>10% of total runtime」。模型只有 64M,本來就吃不掉多少時間,tokenizer 的比重跟著被抬上去。
模型之外的工作
有些工作,模型根本還沒進場。另一個人有一批資料沒辦法把要做語意搜尋的 metadata 存下來,只好每次搜尋都當場把文字轉成 embedding,tokenizing 佔掉九成以上的 CPU 時間。他自己補了原因:預設 tokenizer 的實作很天真,複雜度隨文件長度平方成長,換成一個像樣的 scanner 之後大部分問題就沒了,連 SIMD 都還沒用上。
作者自己的用途也在這一類。他做的是預訓練實驗,資料的混比、過濾、處理方式一改就得重跑一遍,而切分做在 token 這一層,不在文字那一層;這種工作他們是「run for days on a huge number of CPUs」,跑的是 DCLM 那種規模的資料。
再往前一點還有一種,跟百分比沒什麼關係。一個做 AI 平台的人說,他們需要很早就把 token 切出來,後面的分流、流量限制這些判斷都靠它;他也說這在一次請求的端到端時間裡佔比不大,可是還是得做得快。
Gigatoken 自己的數字
工具這一邊也有同樣的落差。Gigatoken 的 README 開頭寫著「~1000x faster than HuggingFace’s tokenizers, drop-in replacement.」,而 benchmark 跑的是 owt_train.txt,一份 11.9 GB 的純文字檔,機器是配 AMD EPYC 9565、合計 144 核。
| Tokenizer | gigatoken | HF tokenizers | 倍率 |
|---|---|---|---|
| GPT-2 | 24.53 GB/s | 24.8 MB/s | 989× |
| Qwen 3 | 22.16 GB/s | 34.2 MB/s | 648× |
| Gemma 1 | 2.51 GB/s | 342.2 MB/s | 7.3× |
機器相同,檔案也沒換,不一樣的只有那一列用的 tokenizer。README 寫著「The slowest rows are the SentencePiece-based tokenizers, which are not well optimized in Gigatoken.」Gemma 系列、Mistral、CodeLlama 這幾列都在同一段範圍裡,倍率全在十幾倍以下。
量測條件本身也決定了數字的大小。gigatoken 讀的是整份沒有切開的檔案,連邊界要落在哪、怎麼自動平行化都得自己處理;HuggingFace tokenizers 拿到的是前 100 MB,tiktoken 拿到前 1 GB,兩邊拿到的內容都事先照 <|endoftext|> 切好了。對照組收到的是一份份完整的文件,不是一個個詞彙。只量前面一段這件事,作者說是公平的,理由是被比的兩套都沒有做快取,速度從頭到尾大致均勻。事先切好這一項,那段沒有另外說明。README 註明,拿來比的兩套本身就是多執行緒的 Rust 程式。
呼叫的方式也差一輪。表上的數字要走 gigatoken 自己的 API 才拿得到。換成相容模式,也就是把現有的 HuggingFace tokenizer 包一層、其他程式都不動的用法,README 說作者在這上面花了不少工夫,讓輸出跟 HuggingFace 對得起來,代價是「a non-negligible cost to performance」,走這條路一樣會快很多,「but not quite the 1000x you will get with the Gigatoken API」。作者給的量級是大概 200 到 300 倍。
延遲跟吞吐量
討論串裡有人算了一個具體的例子:假設 tokenization 花 10 ms、後面的推論步驟花 50 ms,把 tokenization 加快,改善的是到第一個 token 的時間,對吞吐量影響不大;第一個 token 之後,推論本身就把 tokenization 的時間蓋過去了。
這篇是照著 README 跟那串討論整理的,數字多半是當事人自己報的,版本一改可能就對不上;可能有錯,發現的話會盡快修改~

