0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

村人(52)、GB10を激重にする 〜vLLMのパラメータを理解するまで〜

0
Last updated at Posted at 2026-03-07

はじめに

こんにちは。村人(52)こと池駄賃です。誕生日を迎え、52歳になりました。
最近、LLMサーバーを作っていました。が、さすが凡人の鏡ですね。やらかしました。
その顛末をお話しします。


それでは、「始まり始まり〜〜〜〜〜〜〜〜!!!(コンコンコン)」


構成
マシン: ThinkStation PGX(いわゆるDGX Spark)
GPU: GB10
Model: Qwen3.5-27B
Engine: vLLM

私は思いました。
「ついに俺もLLMサーバー運用者か…。それにしてもQwen3.5系の思考過程(think)は美しい」

しかしこの後、村人らしい事件が起きます。



1. vLLMサーバー完成

まずは普通にサーバーを立てました。

vllm serve Qwen/Qwen3.5-27B ...(省略)

クライアントからリクエストを送ります。

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="dummy",
)

resp = client.chat.completions.create(
    model="qwen",
    messages=[{"role":"user","content":"こんにちは"}],
)

print(resp)

動く。完璧です。

そう思っていました



2. ログ

ログを見るとこう書いてあります。
スクリーンショット 2026-03-06 22.38.18のコピー.png

「...え?...4.5 tokens/s.........GB10.........27Bモデルで4.5 tokens/s.........遅すぎる。まさか間違った買い物したのかも.........」

私はちょっと焦りました。



3. LLMサーバーの真実

ここで色々調べていると重要な事実がわかっていました。
LLMサーバーは 1リクエストではGPUが遊ぶ状態 になってしまうらしい。そして、GPUは バッチ処理 で真価を発揮するらしい。

図で説明

1リクエスト
GPU ████░░░░░░░░░░░░ (ほとんど遊んでいる)

複数リクエスト
GPU ████████████████ (フル稼働)

つまり同時リクエストを増やす必要がありそうです。

理由をChatGPTさんに聞きました。GPUとCPUでは役割が全く異なり、

  • CPUは少人数のエリートたち
  • GPUは同じ作業をするのが得意なたくさんの労働者たち

そう、GPUを使う僕たちは労働者の皆さんに奉仕する立場なんですね。
(いやそこじゃない)



4. そこで村人(52)は考えた

原因は並列が少ないってことだな。
「よし。max_num_seqsを増やそう。」
「バカと無知(橘玲さん著)」でいう「無知であり、バカ」な人間が動き始めます。



5. 事件発生

何も考えず、クライアント側からバッチサイズを増やして投げます。
この時、vllmをサーブするときの起動コマンドはこれ

  • サーバー側
vllm serve /home/*****/models/Qwen3.5-27B \
  --served-model-name qwen3.5 \
  --host 0.0.0.0 --port 8000 \
  --gpu-memory-utilization 0.90 \
  --limit-mm-per-prompt.image 0 \
  --limit-mm-per-prompt.video 0 \
  --max-model-len 32768 \
  --async-scheduling

正直、ほとんど何み考えてない


  • クライアント側
バッチ処理の関数は長いのでこのトグルを開いてね
def infer_text(prompt: str) -> str:
    for _ in range(3):  # 最大3回のリトライ
        try:
            response = client.chat.completions.create(
                model="qwen3.5",
                messages=[{"role": "user", "content":  [{"type": "text", "text": prompt}]}],
                max_tokens=16384,
                temperature=0,
                top_p=1,
            )
            return response.choices[0].message.content.strip()
        except Exception as e:
            print(f"Error during inference: {e}. Retrying...")
            time.sleep(1)  # リトライ前に1秒待機
            
def infer_texts(prompts: List[str]) -> List[str]:
    if not prompts:
        return []
    max_workers = len(prompts)
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        return list(executor.map(lambda p: infer_text(p), prompts))

文字列が入ったtopic(list)をバッチ化して並列推論させます。いきなり、長文のインプットを256並列やってみましょう。

batch = 256
topics_batch = [topics[i : i + batch] for i in range(0, len(topics), batch)]
batched_prompt = ["以下のテキストを要約してください。\n" + topic['text'] for topic in topics_batch[0]]

infer_texts(batched_prompt)

実行。

GB10: 激重
SSH: 接続が切れる
top: そもそもSSHで入れん
vLLM: logすら出ない
人生: はちゃめちゃ

頭の中に 敵機来襲 のアラートが鳴り続けます
完全に 「ちょっと待って」 状態になりました。


6. 調査開始

ここからvLLMパラメータを調べ始めました。
すると重要パラメータは意外と少ないことがわかりました。

vLLM重要パラメータ TOP10

  1. max_num_seqs : 同時リクエスト数
    例: --max-num-seqs 64
    意味: 同時処理するリクエスト数
    効果: スループット ↑、 VRAM使用量 ↑

  2. max_num_batched_tokens : 1stepの総トークン数
    例: --max-num-batched-tokens 8192
    requestが三つ来て、2000 tokens × 3 合計: 6000 tokens

  3. max_model_len : 最大コンテキスト
    例: --max-model-len 8192
    大きいと KV cache巨大 -> VRAM消費増

  4. gpu_memory_utilization: GPU使用率
    例: --gpu-memory-utilization 0.9
    VRAMの90%まで使う

  5. tensor_parallel_size: GPU分散
    例: --tensor-parallel-size 1
    GB10の場合、基本はGPUが1枚なのでtensor_parallel_size = 1
    tensor_parallelとはモデルを 複数GPUに分割する仕組みです。
    例えば30Bモデルを4GPUで動かすと 7.5B × 4 に分割。

  6. chunked prefill: 長文のinputを分割
    例: --enable-chunked-prefill

  7. partial prefill: 大きなサイズのprefill途中で別リクエストを受け付け可能

  8. scheduler_delay_factor: バッチ待ち時間

  9. swap_space: CPU退避

  10. block_size: KV cache管理をブロックにして管理するときの単位



7. 実は最重要パラメータ

実はvLLM性能のほとんどは以下で決まるらしい

  • max_num_seqs
  • max_num_batched_tokens

ここを調整するとスループット3〜8倍は普通に変わるそうです(GPTさんによる)



8. 実践チューニング例(GB10)

GB10環境での例

vllm serve Qwen/Qwen3-30B-A3B \
  --tensor-parallel-size 1 \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192 \
  --max-num-seqs 32 \
  --max-num-batched-tokens 8192 \
  --enable-chunked-prefill

GB10はGPUが1枚なのでtensor_parallel_size = 1になります。



9. 村人の学び

今回の流れ

  1. リクエストで満足
  2. tokens/s遅い
  3. 並列増やす
  4. GB10激重
  5. パラメータ調査

という村人(62)らしい凡人丸出しのミスでした。
ミスというのは成長の機会っすね!www



10. 村人(52)は...

うむ
モデルをサーブするだけでも色々あるんだな。知らなかった。
もっと推論について調べないと。特に今はbf16のままサーブしているけど、もっと大きなモデルをサーブするときは量子化も考えないと。
一つ一つがなかなかに奥深い。それがLLM開発なんだな。
おっと、これを書いているとvLLMがバージョンアップしたらしい(タイミング...)
FP8対応とかQwen3.5への正式対応など、色々ありそうなのでしっかりチェックしたいと思います。

11. まとめ

vLLMの引数はちゃんと理解すべし!

  • max_num_seqs
  • max_num_batched_tokens

この二つの理解は必須ですね。
データセットを作るときはインプットトークンがすごく大きくなります。
なので--enable-chunked-prefillをうまく活用したいと思いました!



12. おわりに

「村人(52)の話を聞いてもどうなの?」とは思いますが、僕と同じく vLLM勇者に憧れる人 に届けばいいなと思ってます。
vLLMサーブするだけでも、色々と考えないといけないことが多いっすね。

ばんがろ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?