3行でいうと
- 速さは2つです。入力を読む「prefill(pp)」と、続きを作る「decode(tg)」。単位はどちらもトークン/秒です。
- llama-benchの既定は、pp512、tg128、5回繰り返しの平均です。トークン化とサンプリングの時間は含まれません。
- Ollamaの
eval rateは、生成したトークン数を生成にかかった時間で割った値です。 - Appleの記事は、最初のトークンまでは計算が律速、その後の生成はメモリ帯域が律速だと説明しています。
この記事は、実際に使って確かめた記録ではありません。この記事は公式の文書や論文を読んでまとめたものです。数字の計算は、公式の例から僕らが行ったものです。
先に結論
測るなら、次の2つを別々に記録してください。
- pp(prompt processing):入力文をモデルに読ませる速さ。長い資料を貼るときに効きます。
- tg(text generation):返事を1トークンずつ作る速さ。読んでいて「速い・遅い」と感じるのは、主にこちらです(見立てです)。
1つの「tokens/s」だけが書かれた記事や表は、どちらを指すのか、どの長さの入力で測ったのかが分からないと、比べられません。自分のマシンでは、llama-benchで同じ条件を揃えて測るのが、公式の道具としては一番はっきりしています。
前提:用語
- トークンは、AIが文章を数える単位(文字の断片)です。
- prefillは、入力を読んで内部の記憶(KVキャッシュ)を作る段階です。decodeは、その記憶を使って次のトークンを1つずつ出す段階です。
- TTFT(time to first token)は、送信から最初のトークンが出るまでの時間で、主にprefillにかかる時間です。
- メモリ帯域は、メモリから1秒間に読み出せるデータの量です。
なぜ2つに分けるのか
Appleの機械学習チームの記事(MLXとM5、2025年11月19日)は、「最初のトークンの生成は計算が律速で、2つ目以降のトークンはメモリ帯域が律速」と説明しています。記事には、M4のメモリ帯域が120GB/s、M5が153GB/sで28%高い、とあります。生成速度の向上が19〜27%だったのは、この帯域の差による、と記事は述べています。測定の条件は、プロンプト4,096トークン、追加で128トークンの生成です。
僕らの計算です。「生成1トークンごとに、モデルの重みをほぼ全部読む」と仮定すると、生成速度の上限は、メモリ帯域÷モデルのサイズで見積もれます。たとえば、153GB/sで、Q4_K_Mの8Bモデル(公式の表で4.58GiB、約4.92GB)なら、約31トークン/秒が理論上の上限です。実際の速さは、これ以下になります。この見積もりは、上の記事の説明からの僕らの推測で、記事が式を示しているわけではありません。
llama-bench
llama.cppに付属する測定専用の道具です。READMEによる主な点です。
- 測る種類は3つです。pp(
-p)、tg(-n)、pp+tg(-pg)。 - 既定は、
-p 512、-n 128、-r 5(5回繰り返し)です。結果は、平均のトークン/秒と標準偏差で出ます。 - 各項目はカンマ区切りで複数指定でき、組み合わせの全部を測ります。
-d(深さ)で、あらかじめKVキャッシュにその数のトークンを入れた状態で測れます。- 出力は、md(既定)、csv、json、jsonl、sqlの5種類です。
- READMEに「トークン化とサンプリングの時間は、測定に含まれない」と書かれています。
- 測定の前にウォームアップを行います(
--no-warmupで省略可)。
公式READMEの例です。この記事では、実行していません。
./llama-bench -m model.gguf -p 512,2048 -n 128 -d 0,4096
./llama-bench -m model.gguf -ngl 10,20,30,35
./llama-bench -o csv > result.csv
1行目は、プロンプトの長さ2通りと、深さ2通りを組み合わせて測ります。2行目は、GPUに載せる層の数を変えた比較で、READMEにもこの形の例があります。3行目は、表計算に取り込むためのCSV出力です。
主なオプション(READMEの一覧)です。
| オプション | 意味 | 既定 |
|---|---|---|
-ngl |
GPUに載せる層の数 | -1 |
-t |
CPUのスレッド数 | 環境による |
-b / -ub |
バッチの大きさ / 内部の小バッチ | 2048 / 512 |
-fa |
フラッシュアテンション(on/off/auto) | auto |
-ctk / -ctv |
KVキャッシュの型 | f16 |
-r |
繰り返し回数 | 5 |
CSVやJSONには、使ったCPUとGPUの名前、ビルド番号、各設定が一緒に記録されます。後で見比べるときのために、この出力を残しておくのが便利です(見立てです)。
READMEの例の数字から読めること
READMEの例は、NVIDIAのGPU(CUDA)での結果です。Macの値ではありません。
- 7Bの4ビットモデルでGPUに載せる層を10から35まで増やす例では、tgが13.45から131.66トークン/秒へ、ppが373.36から2400.01トークン/秒へ上がります。全層を載せた最後の段で大きく伸びます。
- バッチの大きさを128から1024にする例では、pp1024が1436.51から2498.61トークン/秒に上がります。
- 深さの例(qwen2 7B Q4_K)では、深さ0でpp512が7340.20、tg128が120.60です。深さ512では、それぞれ6425.91、116.71です。文脈が増えると少し遅くなります。
- CPUのスレッド数の例では、16から32スレッドで、ppは33.52から59.00に伸びる一方、tgは15.32から16.41とほとんど変わりません。
僕らの計算です。深さ512でのppの低下は約12%(6425.91÷7340.20)、tgの低下は約3%(116.71÷120.60)です。
Ollama
Ollamaは、応答のAPIの結果に、時間と数を載せます。ドキュメントの項目は、次のとおりです(時間はすべてナノ秒)。
| 項目 | 意味 |
|---|---|
total_duration |
応答全体にかかった時間 |
load_duration |
モデルを読み込んだ時間 |
prompt_eval_count / prompt_eval_duration |
入力のトークン数 / キャッシュにない入力の処理時間 |
prompt_eval_cached_count |
キャッシュから読んだ入力のトークン数 |
eval_count / eval_duration |
出力のトークン数 / 生成にかかった時間 |
コマンドでは、ollama run モデル名 --verbose で、応答のあとに時間が表示されます(コマンドの説明に「Show timings for response」とあります)。表示の計算は、ソースコードを読むと次のとおりです。
prompt eval rate:キャッシュにない入力のトークン数 ÷ prompt eval durationeval rate:eval_count ÷ eval duration
APIの例から、速さを計算する
ドキュメントの応答の例(gemma4、短い質問)の数字です。
- prompt_eval_count:11、prompt_eval_duration:13,074,791 ns
- eval_count:18、eval_duration:52,479,709 ns
- load_duration:101,397,084 ns、total_duration:174,560,334 ns
僕らの計算です。
- 入力の速さ:11÷0.013074791≒841トークン/秒
- 生成の速さ:18÷0.052479709≒343トークン/秒
- 読み込みは約101ms、全体は約175msです。
ただし、入力11トークン、出力18トークンという短さでは、数字の誤差が大きいはずです。この例は、公式の説明用のもので、実測の目安ではありません。
LM Studio
LM Studioの新しいREST API(POST /api/v1/chat)の応答には、stats が付きます。項目は、input_tokens、total_output_tokens、reasoning_output_tokens、tokens_per_second(生成速度)、time_to_first_token_seconds、model_load_time_seconds(モデルが未読み込みのときだけ)です。
見立てです。この統計は、入力の速さそのものは出さず、TTFTと入力トークン数から推し量る形になっています。LM Studioのアプリ画面に出る統計の表示は、今回読んだ文書では確認できませんでした。
llama-serverとMLX
llama-server:応答の timings に、cache_n(キャッシュから再利用した入力トークン)、prompt_n、prompt_per_second、predicted_n、predicted_per_second などが入ります。文書の例は、prompt_n が1、cache_n が236で、prompt_per_second は32.3です。これは、キャッシュを使って1トークンしか処理しなかった結果なので、「入力を読む速さ」としては参考になりません。キャッシュが効いている応答の prompt_per_second を、そのままprefillの速さと読まないでください。
MLX(Mac):mlx_lm.benchmark というコマンドがあり、ソースコードで確認できる既定は、プロンプト512トークン(-p)、生成1,024トークン(-g)、バッチ1、5回(-n)です。1回の測定ごとに、prompt_tps、generation_tps、peak_memory を出し、最後に平均を出します。ランダムなトークンを入力にし、途中で止まらないよう終了トークンを無効にしています。ピークメモリも出る点は、他の道具との違いです。
測るときの手順
見立てです。
- モデルと量子化を固定する:同じGGUFで比べます。Q4_K_MとQ8_0では、生成の速さが大きく変わります(llama.cppの量子化READMEの表で、Llama-3.1-8Bの生成が約72と約51トークン/秒。測定機材は書かれていません)。
- 短い入力と長い入力の両方で測る:ppは
-p 512,4096、深さは-d 0,4096のように。 - GPU/CPUの割り当てを確認する:llama-benchの表の
backendとnglの列を見ます。 - 回数を重ねる:標準偏差が大きいときは、その値を信用しません。
- 設定ごと残す:CSVかJSONで保存します。
よくある失敗
- 最初の1回を測る:Ollamaの
load_durationのように、モデルの読み込みが入ります。llama-benchはウォームアップをしますが、ほかの道具の画面表示については、文書で確認できていません。 - キャッシュの効いた応答を測る:上のllama-serverの例のとおりです。Ollamaの
eval rateの入力側は、キャッシュ分を除いて計算されます。 - 思考するモデルで出力数を取り違える:LM Studioの統計は、思考のトークンを別に数えています。体感の「返事の速さ」と、トークン/秒は一致しないことがあります。
- 異なる道具の数字を並べる:llama-benchはトークン化とサンプリングを除きます。ほかの道具の統計が何を含むかは、文書で確認できていません。厳密な比較は、同じ道具・同じ条件で行ってください。
気をつけること
- この記事では、ここで紹介した道具を実行していません。実機の数字は、1つも持っていません。
- READMEの例や文書の例の数字は、特定の機器・モデルでの値です。自分のマシンの結果ではありません。
- 「生成の上限は帯域÷モデルのサイズ」は、僕らの推測を含む目安です。MoEモデル、量子化の形式、KVキャッシュの読み出しなどで、実際はずれます。
- LM Studioのアプリ内の統計表示と、llama-benchの
-dと実際の長い会話の対応は、確認できていません。 - 各道具のオプションや表示は、バージョンで変わります。llama.cppのREADMEは、2026年10月8日にmasterブランチで読みました。
出典
- llama-bench README(llama.cpp、ggml-org、2026年10月8日確認)
- llama-server README(llama.cpp、ggml-org、2026年10月8日確認)
- Generate a response(Ollama docs、Ollama、2026年10月8日確認)
- api/types.go(Ollama、2026年10月8日確認)
- cmd/cmd.go(Ollama、2026年10月8日確認)
- Chat(LM Studio Developer Docs、LM Studio、2026年10月8日確認)
- mlx_lm/benchmark.py(mlx-lm、Apple、2026年10月8日確認)
- Exploring LLMs with MLX and the Neural Accelerators in the M5 GPU(Apple Machine Learning Research、Apple、2025年11月19日、2026年10月8日確認)
- llama-quantize README(llama.cpp、ggml-org、2026年10月8日確認)
更新履歴
- 2026年10月25日 書き方を直しました。
- 前:運営者が使っていないと読める書き方 → いま:「この記事は、実際に使って確かめた記録ではありません」。公式の資料を読んでまとめた記事で、使い心地は書いていない、という意味に直した
