「GPU代を出してサーバーを強化する前に、本当に必要なスペックを数字で把握しておきたい」
そんな悩みを抱えるインフラエンジニアやLinux管理者は多いはずです。この記事では、Ollamaをcurlとwrkで負荷テストする方法を、トークン毎秒(TPS)・初回トークン到達時間(TTFT)・同時接続上限・GPU使用率の4指標を実測する手順を中心に解説します。測定結果から本番サーバーに必要なスペックを算出し、スケールアップ投資の判断基準を数字で出せるようになることを目指します。OllamaをUbuntu Serverに構築する前提手順はUbuntu ServerでローカルLLMを構築する方法を参照してほしい。
この記事のポイント
・curlの-wオプションでTTFT・総レスポンスタイムを1コマンドで計測できる
・wrkの-cオプションで並列接続数を上げながらスループット上限を特定できる
・Pythonのasyncioで同時接続を段階的に増やし、エラーが出始めるラインをつかめる
・GPU VRAM使用率と応答速度の相関を見るとスペック判断の根拠が明確になる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
負荷テストで把握すべき4つの指標
Ollamaの本番運用前に把握しておくべき指標は4つある。・TTFT(Time To First Token): ユーザーが入力を送ってから最初のトークンが返るまでの時間。体感レスポンス速度に直結する
・TPS(Tokens Per Second): 1秒あたりに生成できるトークン数。出力の流暢さを決める
・同時接続上限: エラーなく並列リクエストを捌ける最大接続数。チームの同時利用人数の上限になる
・VRAM使用率: GPUメモリの占有率。モデルをスワップアウトせずにGPU上に保持できるかどうかの指標
この4指標がわかると「現在のGPUで最大何人が同時に快適に使えるか」「スペックを上げた場合の改善量はどの程度か」が数字で答えられるようになる。感覚や口コミではなく実測値で意思決定できるのが最大の価値だ。
適切なモデルを選んでおくことが負荷特性にも影響するため、テスト前にモデル選定を済ませておくとよい。ローカルLLMのモデルを比較する方法にLlama3.3・Mistral・Gemma 3・Phi-4の性能差をまとめている。
curlで単発リクエストの基準値を計測する
まず1リクエストの基準値を計測する。並列テストの比較ベースになるため、この数字が正確でないと全体の分析がずれる。1. 計測フォーマットファイルの準備
curlの`-w`オプションにフォーマット文字列を渡すと、DNS解決・接続・転送の各フェーズのタイムを細かく計測できる。$ cat > /tmp/curl-format.txt <<'EOF' time_namelookup: %{time_namelookup}\n time_connect: %{time_connect}\n time_starttransfer: %{time_starttransfer}\n time_total: %{time_total}\n EOF
2. 非ストリーミングモードで単発計測する
負荷テストでは再現性を確保するため、`stream: false`で全出力をまとめて返すモードを使う。ストリーミング計測は接続を長時間保持するためwrkとの相性が悪い。$ curl -s -o /dev/null -w "@/tmp/curl-format.txt" \ -X POST http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{"model":"llama3.3:8b-instruct-q4_0","prompt":"Linuxのtopコマンドの使い方を50字以内で説明してください","stream":false}' time_namelookup: 0.000031 time_connect: 0.000060 time_starttransfer: 3.241890 time_total: 3.242100
3. ループ10回で中央値を算出する
$ for i in $(seq 1 10); do curl -s -o /dev/null -w "%{time_total}\n" \ -X POST http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{"model":"llama3.3:8b-instruct-q4_0","prompt":"Linuxのtopコマンドの使い方を50字以内で説明してください","stream":false}' done | sort -n | awk 'NR==5 || NR==6 {sum+=$1; count++} END {print "median:", sum/count, "sec"}' median: 3.287 sec
wrkで並列スループットを測定する
単発の基準値が出たら、並列接続を増やして限界を探る。wrkはHTTP負荷テストツールとして広く使われている。Ollamaへの長時間リクエストにも対応できる。1. wrkのインストール
$ sudo apt install wrk -y $ wrk --version wrk 4.1.0 [epoll] Copyright (C) 2012 Will Glozer
2. POSTリクエスト用のLuaスクリプトを作成する
wrkのデフォルトはGETリクエストのみ対応している。Ollamaへの推論APIはPOSTリクエストが必要なため、Luaスクリプトで設定する。$ cat > /tmp/ollama-wrk.lua <<'EOF' wrk.method = "POST" wrk.headers["Content-Type"] = "application/json" wrk.body = '{"model":"llama3.3:8b-instruct-q4_0","prompt":"Linuxのtopコマンドの使い方を50字以内で説明してください","stream":false}' EOF
3. 接続数を段階的に増やして上限を探る
並列接続数を1→2→4→8と倍増させながら、スループットとエラー率の変化を観察する。タイムアウトはLLMの推論時間に合わせて120秒以上に設定する点が重要だ。$ for c in 1 2 4 8; do echo "=== concurrency: $c ===" wrk -t2 -c${c} -d30s -T120s -s /tmp/ollama-wrk.lua \ http://localhost:11434/api/generate 2>&1 | grep -E "Requests|errors|Socket" done === concurrency: 1 === Requests/sec: 0.30 === concurrency: 2 === Requests/sec: 0.27 === concurrency: 4 === Requests/sec: 0.14 === concurrency: 8 === Requests/sec: 0.09 Socket errors: connect 0, read 6, write 0, timeout 4
Pythonの非同期スクリプトで同時接続上限を精緻に測定する
wrkはHTTPの短距離レース向けに設計されているため、数秒以上かかるLLM推論では計測精度が下がることがある。Pythonのasyncioとaiohttpを使うと、タイムアウト・エラーカウント・レスポンス時間の分布を詳細に計測できる。1. aiohttpで並列リクエストを送るスクリプトを書く
$ cat > /tmp/ollama_load_test.py <<'EOF' import asyncio, aiohttp, time, statistics CONCURRENCY = 4 # ここを変えながらテスト URL = "http://localhost:11434/api/generate" PAYLOAD = { "model": "llama3.3:8b-instruct-q4_0", "prompt": "Linuxのtopコマンドを50字以内で説明してください", "stream": False } async def request(session, sem, results): async with sem: t0 = time.time() try: async with session.post( URL, json=PAYLOAD, timeout=aiohttp.ClientTimeout(total=120) ) as r: await r.json() results.append(("ok", time.time() - t0)) except Exception: results.append(("err", time.time() - t0)) async def main(): sem = asyncio.Semaphore(CONCURRENCY) results = [] async with aiohttp.ClientSession() as session: await asyncio.gather( *[request(session, sem, results) for _ in range(CONCURRENCY * 3)] ) ok = [t for s, t in results if s == "ok"] err = [t for s, t in results if s == "err"] print(f"CONCURRENCY={CONCURRENCY} OK:{len(ok)} ERR:{len(err)}") if ok: print(f"avg={statistics.mean(ok):.2f}s median={statistics.median(ok):.2f}s max={max(ok):.2f}s") asyncio.run(main()) EOF $ pip install aiohttp -q $ python3 /tmp/ollama_load_test.py CONCURRENCY=4 OK:12 ERR:0 avg=6.83s median=6.71s max=8.42s
2. CONCURRENCY値を増やしながらエラーラインを特定する
スクリプトのCONCURRENCY変数を4→8→12→16と増やしながら実行する。ERRが0から増え始めた値がOllamaの実用的な並列上限だ。この上限がチームの同時利用可能人数の目安になる。社内でのChatGPT代替としてOllamaを展開する場面での判断基準については機密データを守るローカルLLMという選択肢も参考になる。
nvidia-smiでGPU・VRAMのボトルネックを特定する
レスポンスが遅い原因がGPU演算なのかVRAM不足なのかを切り分けることで、対処法が変わる。負荷テストと並行してGPU状態を記録する。1. 負荷テスト中にGPUログを取得する
別ターミナルでnvidia-smiを1秒間隔で記録しながら、メインターミナルで負荷テストを実行する。# 別ターミナルで実行(テスト終了後にCtrl+Cで停止) $ nvidia-smi \ --query-gpu=timestamp,utilization.gpu,utilization.memory,memory.used,memory.free \ --format=csv,noheader -l 1 > /tmp/gpu_log.csv # テスト後に平均値を集計 $ awk -F', ' '{gsub(/ %/,"",$2); gsub(/ %/,"",$3); sum_gpu+=$2; sum_mem+=$3; count++} END {printf "avg GPU util: %.1f%% avg MEM util: %.1f%%\n", sum_gpu/count, sum_mem/count}' \ /tmp/gpu_log.csv avg GPU util: 87.3% avg MEM util: 94.1%
2. 計測値からボトルネックを判断する
GPU使用率とVRAM使用率の組み合わせで対処法が変わる。・GPU使用率90%以上 + VRAM余裕あり: GPU演算がボトルネック。より高性能なGPUへの交換が有効
・VRAM使用率90%以上: モデルの一部がRAMにスワップしている。量子化を下げるかVRAMを増やす
・GPU使用率50%以下でレスポンスが遅い: CPUとのデータ転送かI/Oがボトルネック。PCIeの帯域を確認する
・VRAM使用率60%以下でエラーが出る: OLLAMA_NUM_PARALLELが小さすぎる可能性がある
先ほどの例(GPU 87%・VRAM 94%)はGPU演算とVRAMの両方が限界に近い状態だ。並列接続数を増やすなら、より小さい量子化モデルへの切り替えか、VRAMの増設を先に検討する。
実測値から本番スペック要件を算出する
1. 必要スループットを利用人数から逆算する
チームの想定同時利用人数と1リクエストあたりの所要時間から、必要なキャパシティを計算する。例として「20名チームが業務時間(8時間)に1人あたり1時間で5回Ollamaを呼び出す」ケースを想定する。
・ピーク時の同時リクエスト: 20名 × 5回 / 8時間 = 12.5 req/h ≒ 0.0035 req/sec(均等分散)
・ただし実際は休憩明けや会議後に集中する。ピーク係数3倍で 0.0035 × 3 = 0.01 req/sec
・単発基準値 3.3秒/req → 理論上限 0.30 req/sec
・必要キャパ 0.01 req/sec に対して現状 0.30 req/sec → 単純計算では余裕があるように見える
ただし上記は逐次処理の場合だ。ユーザーがリアルタイムで待つ体験を考えると、同時接続数が実質的な制約になる。「朝9時に5人が一斉に使い始める」といった使われ方では、同時接続上限(前節で計測した3~4)が先にボトルネックになる。
2. スペックアップの費用対効果を試算する
VRAM不足が原因の場合、モデルの量子化を下げると改善できる。`llama3.3:70b-instruct-q4_0`(約40GB)から`llama3.3:8b-instruct-q4_0`(約5GB)に変えると同じ24GB GPUでも3~4モデルを同時保持できる。GPUの交換を検討する場合は、VRAM容量の倍増が同時接続数の倍増にほぼ比例する。RTX 4090(24GB)からA100(80GB)へのアップグレードで、理論上は同時接続数が3~4倍になる計算だ。
よくある落とし穴と注意事項
Ollamaの負荷テストを初めて行う際によく踏む落とし穴を整理する。 wrkのデフォルトタイムアウトで全リクエストがエラーになるwrkのデフォルトタイムアウトは2秒だ。LLMの推論は数秒から数十秒かかるため、`-T`オプションを省略するとほぼ全リクエストがタイムアウトエラーになる。必ず`-T120s`(120秒)以上を指定する。
# -T120s を省略するとタイムアウトだらけになる(NG例) $ wrk -t2 -c4 -d30s -s /tmp/ollama-wrk.lua http://localhost:11434/api/generate # 正しい書き方 $ wrk -t2 -c4 -d30s -T120s -s /tmp/ollama-wrk.lua http://localhost:11434/api/generate
Ollamaは最初のリクエスト時にモデルをGPUにロードするため、初回は通常より数十秒遅くなる。テスト前に`ollama run llama3.3:8b-instruct-q4_0 "テスト"`でウォームアップしてからテストを始める。
nvidia-smiの記録間隔が粗くてスパイクを見逃す
`-l 1`の1秒間隔では短時間のGPUスパイクを見逃すことがある。30秒以内の短い負荷テストには`-l 1`でも概ね問題ないが、精密な計測には`nvidia-smi dmon -d 1`(サブコマンド版)や`watch -n 0.5 nvidia-smi`で確認間隔を短縮する手もある。
チューニングなしでテストしていない
OLLAMA_NUM_PARALLELやOLLAMA_FLASH_ATTENTIONといった環境変数を設定していない素の状態でテストすることが多い。本番環境でこれらを設定する場合は、設定後に必ず再計測して比較する。パラメータ調整の詳細はパフォーマンスチューニング記事を参照してほしい。
まとめ
Ollamaの負荷テストを体系的に行うことで、「何人まで使えるか」「どのスペックが必要か」を感覚ではなく実測値で答えられるようになる。curlで基準値を取り、wrkで並列スループットを測り、Pythonで上限を精緻に探り、nvidia-smiでGPUのボトルネックを特定する4段階のアプローチが、再現性の高いキャパシティプランニングにつながる。| ツール | 計測対象 | 主要コマンド |
|---|---|---|
| curl -w | 単発TTFT・総レスポンスタイム | curl -w "@/tmp/curl-format.txt" -X POST http://localhost:11434/api/generate |
| wrk | 並列スループット・エラー率 | wrk -t2 -c4 -d30s -T120s -s ollama-wrk.lua http://localhost:11434/api/generate |
| Python asyncio | 同時接続上限・エラーラインの特定 | asyncio.Semaphore(CONCURRENCY)で並列数を段階的に制御 |
| nvidia-smi | GPU使用率・VRAM消費量の推移 | nvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv -l 1 |
Ollamaの負荷テストと本番スペック設計を2日間のハンズオンで体験する
curlとwrkの計測からGPUボトルネックの特定まで、実機で手を動かしながら習得するのが最短ルートだ。実機GPU環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:OllamaのセキュリティをLinuxで強化する方法|iptables・Dockerネットワーク隔離・Fail2banでローカルLLMサーバーを保護する手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます