SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-22

Ollamaの同時実行数と待機キューを設定する方法

Ollamaでは2番目のリクエストは通常キューで待機し、満杯ならHTTP 503で拒否されます。OLLAMA_NUM_PARALLELとOLLAMA_MAX_QUEUEの設定、各スロットがKV cacheとVRAMを消費する理由を解説します。

Ollama で最初のリクエストの生成中に 2 番目のリクエストがどう処理されるか

Ollama の同時実行数は 3 つの環境変数で決まります。初期状態では、1 つのロード済みモデルが一度に処理できるリクエストは 1 つです。2 番目のリクエストは拒否されず、途中までの回答も返りません。空きスロットができるまでキューで待機し、その後に通常の速度で処理されます。

受信したリクエストの処理結果は 3 通りです。空きスロットがあれば直ちに開始します。空きがなければキューで待機します。キューも満杯の場合は、サーバーが HTTP 503 で拒否します。どの結果になるかは OLLAMA_NUM_PARALLELOLLAMA_MAX_QUEUEOLLAMA_MAX_LOADED_MODELS で決まります。

初期値は安全です。しかし、問題が発生していないのに 2 人目のユーザーがサーバーが「ハングした」と報告する原因にもなります。スロットの追加は 2 行の変更で済みます。注意が必要なのはメモリです。各並列スロットには専用の key/value cache (KV cache) が必要です。これは、モデルが処理済みのトークンを保持するメモリ領域です。VRAM (GPU 上のビデオメモリ) を増やさずにスロットを追加すると、遅い回答ではなくロード失敗が発生します。

OLLAMA_NUM_PARALLELOLLAMA_MAX_LOADED_MODELSOLLAMA_MAX_QUEUEが制御する内容

これらは、2026年8月時点の現在の Ollama リリースにおけるデフォルト値です。以下に示すログ行を使って、自分の環境の値を確認してください。ここに記載した数値をそのまま信頼しないでください。

  • OLLAMA_NUM_PARALLEL は、1つのロード済みモデルが同時に処理できるリクエスト数です。デフォルトは1です。そのため、リクエストは1件ずつ処理されます。
  • OLLAMA_MAX_LOADED_MODELS は、異なるモデルを同時に常駐させる数です。デフォルトは0です。この場合、Ollama が値を選択します。GPU 1台につき3モデル、GPUがないマシンでは3モデルです。
  • OLLAMA_MAX_QUEUE は、待機させられるリクエスト数です。デフォルトは512です。キューが満杯の状態で到着したリクエストは、直ちに拒否されます。

最悪時に必要なメモリ量は、最初の2つの値の積で決まります。ロード済みモデル2つがそれぞれ4スロットを使用する場合、KV cache は合計8スロット分割り当てられ、すべて同時に常駐します。Ollama はこの状態を満たそうとします。GPU 1台のマシンでは、通常、1つのモデルを保持してスロットを割り当てるほうが適しています。必要な計算を暗算できる範囲に抑えられるためです。

すべての並列スロットが VRAM を消費する理由

Ollama がモデルを読み込むと、専用の runner プロセスを起動します。ここで重要なのは、渡される 2 つの引数です。-c は runner が KV cache 用に確保するコンテキスト全体で、-np は並列シーケンス数です。Ollama は -c を、リクエストごとのコンテキスト長にスロット数を掛けた値に設定します。runner はその合計をスロット間で均等に分割するため、各リクエストには指定したコンテキスト長が割り当てられます。

制約はこれだけです。これが、並列化にコストがかかる理由です。同じリクエストごとのコンテキスト長でスロットを 1 つから 4 つに増やすと、KV cache は 4 倍必要になります。スロット間で共有されるものはなく、アイドル状態のスロットに割り当てられた領域が、処理中のスロットへ貸し出されることもありません。分割は runner の起動時に固定されるためです。

設定したつもりの値ではなく、実際の値を確認できます。

journalctl -u ollama --no-pager -n 500 | grep "starting llama-server"

この行には、-c-np を含む runner の完全なコマンドラインが表示されます。変数を設定した後も -np が 1 なら、その設定はサーバーに渡っていません。次のセクションで、その理由を説明します。

モデルの重みと KV cache の合計が VRAM に収まらない場合、Ollama は一部のレイヤーを system RAM に移し、それらを CPU で実行します。CPU 上のレイヤーは GPU 上のレイヤーより大幅に遅いため、最初は 1 件だけだったリクエストを含め、すべてのリクエストが遅くなります。そのため、並列数を増やすとスループットが向上せず、低下する場合があります。十分に大きなモデルでは、スロット数の計算を始める前に重みだけで容量が決まります。したがって、Kimi K3 のような規模のモデルをセルフホストすることでは、設定するスロット数よりも搭載するカードの枚数が問題になります。

ollama ps

PROCESSOR 列が 100% GPU なら、全体が VRAM に収まっています。35%/65% CPU/GPU のような分割表示は、モデルの一部が CPU で実行されていることを示します。SIZE 列には KV cache も含まれるため、スロット数を増やしてモデルを再読み込みすると値が増えます。OLLAMA_NUM_PARALLEL を増やして再起動し、1 件リクエストを送信してから、もう一度 ollama ps を実行します。これで変更によるメモリ消費量を推測ではなく実測できます。測定結果からモデルが収まらなくなったことが分かった場合は、重みも同じ予算の半分を占めることを忘れないでください。fp16 から q8 または q4 ビルドへ移行することで、追加しようとしていたスロットのコストより多くの VRAM を空けられる場合があります。

コンテキスト長とスロット数は掛け合わせて計算されるため、同時に選択する必要があります。4 スロットで大きなコンテキストを使用すると、大きなコンテキストが 4 つ必要です。モデルの num_ctx コンテキストウィンドウも調整している場合は、2 つの値を一度に 1 つだけ変更してください。そうしないと、どちらの変更で VRAM が満杯になったのか分からなくなります。

再起動後も変数を保持する方法

Linux では、Ollama は systemd サービスとして実行されます。シェルで export OLLAMA_NUM_PARALLEL=4 を実行しても何も変わりません。systemd は独自の環境でサービスを起動し、シェルの環境を参照しないためです。drop-in ファイルを使用します。

sudo systemctl edit ollama.service

開いたエディターに次の内容を追加します。

[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_MAX_QUEUE=32"

その後、設定を再読み込みして再起動します。

sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment

systemctl show は、systemd がプロセスに渡す環境変数を表示します。ここに変数がなければ、drop-in が保存されていないか、daemon-reload を実行していません。サーバー側でも確認します。

journalctl -u ollama --no-pager | grep "server config" | tail -1

Ollama は起動時に環境変数全体を記録します。そのログ行の message は server config です。このマップが実際の状態を示します。変数が有効になったかどうかを確認する最も確実な方法です。

すでにロードされているモデルは、起動時に設定されたスロット数を維持します。この値は起動時に runner プロセスへ固定されるためです。上記の再起動ですべてのモデルがアンロードされるため、次のリクエストで新しい設定を使用してモデルが再ロードされ、ロード時間が1回発生します。その後モデルを常駐させる期間は別の設定であり、リクエスト間で Ollama モデルをロードしたままにする方法で説明します。

クライアントから見た処理済み、キュー待ち、拒否の違い

複数のリクエストを同時に送信し、それぞれの時間を計測します。次のコマンドは、8 個のストリーミングリクエストを並列実行し、各リクエストのステータスと処理時間を表示します。

for i in $(seq 1 8); do
  curl -s -o /dev/null \
    -w "req$i http=%{http_code} ttfb=%{time_starttransfer}s total=%{time_total}s\n" \
    http://127.0.0.1:11434/api/generate \
    -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":true}' &
done
wait

ttfbはストリームの最初のバイトまでの時間です。最初のストリーミングチャンクに最初のトークンが含まれるため、最初のトークンまでの時間(TTFT)に近い値になります。

並列処理。 すべてのリクエストで ttfb がほぼ同じになり、total もすべて同時に増加します。実行中のスロット間で GPU を共有するため、各応答は単独で処理する場合より遅くなります。一方で、1 分あたりに完了する応答数は増えます。OLLAMA_NUM_PARALLEL を増やしたときに得られるのは、この動作です。

キュー待ち。 最初のリクエストにはすぐ応答が返り、後続のリクエストでは大きな ttfb の後に通常どおり生成が始まります。この待ち時間はモデルではなく、キューによるものです。チャット画面を見ているユーザーには、長い空白時間の後、通常の速度でテキストが表示されます。開始は遅いものの、その後は速いという形は、GPU の過負荷ではなくキュー待ちの特徴です。

拒否。 クライアントはほぼ即座に http=503 を受け取り、本文は次のようになります。

{"error":"server busy, please try again.  maximum pending requests exceeded"}

このメッセージは、リクエストの到着時点でキューが満杯だったことを示します。VRAM の容量やモデルの状態を示すものではありません。

1 つ、明確な制限があります。Ollama はキューの深さを公開していません。ollama ps/api/ps エンドポイントが報告するのはロード済みモデルであり、待機中のリクエストではありません。そのため、クライアント側で最初のバイトまでの時間を監視してキューを計測するか、手前にあるコンポーネントで 503 応答の数を数えます。

MAX_QUEUE を小さくするほうが適切なことが多い理由

512 のキューは十分に大きく見えますが、処理スロットが 1 つだけの場合、その大部分はほとんど役に立ちません。Request 300 は、完了まで 299 件の生成処理の後ろで待機します。最短でも数分かかります。すべての HTTP クライアントはそれよりはるか前に諦めるため、呼び出し元からはクライアント側のタイムアウトに見えます。これでは原因を判断できず、監視からのアラートも発生しません。

キューは、クライアントのタイムアウト時間内にサーバーが処理できる量を目安に設定してください。上限を超えた要求は、代わりに即座に 503 になります。503 には利点があります。リバースプロキシは再試行でき、クライアントはバックオフでき、ダッシュボードは件数を集計でき、人が内容を確認できます。値は自分の測定結果から算出してください。1 回の生成に約 10 秒かかり、クライアントの待機時間が 60 秒であれば、その時間内に処理できるのは 1 スロットあたり約 6 件です。これより大幅に深いキューを設定しても、タイムアウトが増えるだけです。

Ollama の前段にキューを置くタイミング

組み込みキューは先入れ先出し(FIFO)で、呼び出し元を識別しません。1 つのアプリケーションが 1 台のサーバーと通信する構成なら、これで十分です。インフラを追加すると、障害要因が増えるだけです。次のいずれかに該当する場合は、前段の仕組みを検討します。

  • 優先度が必要な場合。対話型チャットがバッチ要約ジョブの後ろで待たされるべきではありません。Ollama のキューには優先度がないため、バッチ処理は外部で保留し、少しずつ投入する必要があります。
  • 公平性が必要な場合。1 つのクライアントだけでキューを埋められるため、他のクライアントは 503 を受け取ることになります。
  • 再起動後もジョブを保持する必要がある場合。キューはサーバーのメモリ上にあります。Ollama を再起動すると、待機中のリクエストはすべて失われます。
  • バックオフ付きの実際のリトライが必要で、後から確認できる場所に記録したい場合。

軽量な構成はリバースプロキシです。nginx では、limit_conn が同時接続数を制限し、limit_req がクライアントごとの到着レートを制限します。そのため、超過分はプロキシで拒否され、Ollama のキューには到達しません。重量級の構成は、Ollama を呼び出すワーカーの前段にデータベース付きのジョブキューを置く方法です。リクエストをプロセスの再起動後も保持する必要が生じたら、この構成を選びます。実際のトラフィックに合わせたサイジングは別途検討が必要です。同時ユーザー向けの self hosted LLM の計画では計算方法を説明し、VPS での Ollama の実行では、これらの変数が前提とする基本インストールを扱います。

別のサーバーを選ぶべき場合

調整では解決できない制限があります。Ollama はモデルの読み込み時に、KV キャッシュを同じサイズの固定スロットに分割します。アイドル状態のスロットのメモリを、使用中のスロットで利用することはできません。また、モデルをアンロードしない限り、スロット数も変更できません。この設計は、1 人のユーザー、少人数のチーム、またはコーディングエージェントに適しています。

多数のユーザーが同時に利用するよう設計されたサーバーは、動作が異なります。KV キャッシュを小さなページ単位で必要に応じて割り当て、実行中のバッチに新しいリクエストを追加します。そのため、メモリは固定分割ではなく実際の需要に応じて使用されます。1 台の GPU で多数のユーザーを同時に処理することが目標なら、このアーキテクチャの違いは OLLAMA_NUM_PARALLEL の値より重要です。Ollama と vLLM の比較で、この判断を行います。ただし、原則だけで切り替えてはいけません。別のサーバーは運用の手間が増えます。利用者が数人であれば、組み込みの動作が適切です。

自分のスループットと time to first token を測定する

公開されている tokens per second の数値は、別の GPU、モデル、量子化設定、コンテキスト長、プロンプトで測定されたものです。これらは手元の環境とは一致しないため、見かけた数値は大まかな目安として扱い、実際に使用するマシンで測定してください。

Ollama は、すべてのレスポンスの最後の JSON オブジェクトにタイミング情報を返します。eval_count は生成されたトークン数で、eval_duration はその生成にかかった時間をナノ秒で示します。

sudo apt install -y jq
curl -s http://127.0.0.1:11434/api/generate \
  -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":false}' \
  | jq '{prompt_eval_count, eval_count, eval_duration, tokens_per_second: (.eval_count / (.eval_duration / 1000000000))}'

まず 1 スロットで実行し、次に実際に想定する同時実行数で実行して、ユーザーの満足度を左右する 2 つの数値を比較してください。time to first token と、リクエストあたりの tokens per second です。スロットを追加すると、リクエストあたりのスループットは必ず低下します。重要なのは、ユーザーが許容できる範囲を超えて低下するかどうかです。ローカル LLM で tokens per second を測定するでは、実行間でプロンプトを一定に保つ方法を含め、この手順を詳しく説明しています。

余裕のあるキューを持つ公開エンドポイントは、DoS 攻撃の標的になります

OLLAMA_HOST=0.0.0.0:11434 を設定すると、API はすべてのインターフェイスで待ち受けます。Ollama には組み込みの認証機能がありません。デフォルトのキューを使用する公開エンドポイントは、見つけた誰からでも 512 件の待機リクエストを受け付けます。このキューを埋めるのに、攻撃者はほとんどコストを必要としません。長いプロンプト、ログイン不要、レート制限なし、料金もかかりません。その間、正規のユーザーには 503 応答や長い待ち時間が発生し、マシンは処理を続けてリソースを消費します。

リスナーは loopback に限定し、SSH トンネルまたはプライベートネットワーク経由で接続してください。または、手前に認証とレート制限を配置してください。Ollama API エンドポイントの保護では、両方の方法を説明しています。キューの長さを調整するのは、その対策を終えてからにしてください。キューの長さは容量設定であり、セキュリティ対策にはならないためです。

FAQ

2 回目の Ollama リクエストは、なぜ 1 回目が終わるまで待機するのですか?

OLLAMA_NUM_PARALLEL のデフォルト値が 1 だからです。ロード済みモデルは一度に 1 件のリクエストだけを処理し、残りは順番に待機します。待機中のリクエストは HTTP 接続を開いたままにし、スロットが空くまでデータを送信しません。そのため、クライアントからはモデルの処理が遅い場合と同じように見えます。タイミングの形状で判別できます。長い停止の後にテキストが通常の速度で流れる場合はキューです。最初のトークンから少しずつ流れる場合は、モデル自体の処理が遅い状態です。systemd の drop-in でスロット数を増やし、サービスを再起動してください。

「server busy, please try again. maximum pending requests exceeded」とはどういう意味ですか?

これは Ollama が返すキューあふれのエラーで、HTTP status 503 とともに返されます。待機中のリクエスト数が OLLAMA_MAX_QUEUE に達しました。デフォルト値は 512 です。そのため、新しいリクエストは追加されず拒否されました。メモリエラーでもモデルエラーでもありません。キューを増やすだけでは、同じ拒否が発生するまでの待ち時間が長くなるだけです。実際の対策は、VRAM に余裕がある場合はスロットを増やすこと、受信負荷を下げること、または再試行と優先順位付けに対応したキューを前段に置くことです。

OLLAMA_NUM_PARALLEL を増やすと Ollama は高速になりますか?

いいえ。同時に処理できるリクエスト数は増えますが、1 つの GPU を共有するため、各リクエストは単独で実行する場合より遅くなります。また、Ollama は context length にスロット数を掛けた合計コンテキストで runner を起動するため、KV cache もスロット数に応じて増加します。結果が VRAM に収まらなくなると、Ollama は一部のレイヤーを CPU に移し、競合のない単独のリクエストも含めて、すべてのリクエストが遅くなります。変更後に ollama ps を確認し、PROCESSOR 列が引き続き 100% GPU と表示されることを確認してください。

これらの変数を変更した後、Ollama を再起動する必要はありますか?

はい。サーバーは起動時にこれらの変数を読み込みます。また、実行中のモデルは、runner process の起動時に設定されたスロット数を保持します。sudo systemctl edit ollama.service で drop-in を編集し、続いて sudo systemctl daemon-reloadsudo systemctl restart ollama を実行してください。systemctl show ollama --property=Environment で確認し、その後、実際にサーバーが読み込んだ環境を一覧表示する journalctl -u ollamaserver config 行を確認してください。

並列スロットはいくつに設定すべきですか?

1 から始め、1 段階ずつ増やしてください。各段階で Ollama を再起動し、モデルをロードするためのリクエストを 1 件送信してから、ollama ps を実行します。PROCESSOR100% GPU のままで、かつ SIZE 列に、提供する最長のコンテキスト用の余裕が残る最後の値で止めてください。その設定で実際の同時実行数における first token までの時間と tokens per second を測定し、リクエストごとの速度が利用者の許容範囲を下回る場合は、1 段階戻してください。

#ollama#concurrency#vram#queueing#self-hosted-llm