GPUStack v2.1.1 マルチノード推論が起動しない問題を全部つぶした話

GPUStack v2.1.1 マルチノード推論が起動しない問題を全部つぶした話

4 min read

 
Tech Blog
GPUStack
Multi-Node vLLM
Tesla V100
Troubleshooting

GPU クラスタ運用メモ

GPUStack v2.1.1 マルチノード推論が起動しない問題を全部つぶした話
2ノード4×V100 で Qwen2.5-32B を動かすまでの全記録 #

GPUStack v2.1.1 + vLLM バックエンドで、2台の GPU ワーカー(各 Tesla V100-PCIE-32GB × 2枚)を使ったマルチノード分散推論を試みたところ、次々と異なる問題が発生しました。Ray のクラスター接続失敗、Gloo の通信エラー、/dev/shm 不足、V100 固有の CUDA カーネルエラーまで、すべてのトラブルとワークアラウンドを時系列で記録します。

GPU-Worker-A: / Tesla V100×2  |  GPU-Worker-B: / Tesla V100×2  |  GPU-Server: GPUStack Server  |  GPUStack v2.1.1 / vLLM 0.17.1 / CUDA 12.9

構成概要 #

管理ノード(GPU-Server)が GPUStack Server を担当し、推論は GPU ワーカー 2 台に分散。モデルは NFS 共有の /models に格納。Qwen3.5-35B-A3B(VLM)から始まり、最終的に Qwen2.5-32B-Instruct で安定動作を確認。

ターゲットモデル #

Qwen2.5-32B-Instruct(float16)
tensor-parallel×2 / pipeline-parallel×2

GPU 構成 #

Tesla V100-PCIE-32GB × 4枚
(2ノード × 2枚)
compute capability 7.0

最終結果 #

16.46 Tokens/s で安定稼働
max-model-len: 8192
ワークアラウンド適用済み

発生した問題と解決の全体像 #

 

問題 1

Ray Placement Group が永遠に待機する #

モデルを起動すると Waiting for creating a placement group が 10秒 → 30秒 → 150秒 → 630秒と延々と続き、モデルが立ち上がらない。

WARNING: Tensor parallel size (4) exceeds available GPUs (2).
INFO: Waiting for creating a placement group of specs for 630 seconds.
specs=[{'node:': 0.001, 'GPU': 1.0}, {'GPU': 1.0}, {'GPU': 1.0}, {'GPU': 1.0}]

原因:Ray はヘッドノード側のコンテナ内でのみ動作しており、もう一方のワーカーノードの GPU が Ray クラスターに参加できていなかった。

確認コマンド:vllm runner コンテナ内で ray status --address=<HEAD_IP>:41000 を実行。
Ray バージョン不一致エラー(2.54.0 vs 2.48.0)が出た場合は GPUStack イメージのバージョン齟齬が疑われる。
 

問題 2

/etc/hosts の 127.0.1.1 エントリによる Gloo 通信失敗 #

Ray ノード間では接続できているのに、モデルロード後の分散環境初期化(Gloo の connectFullMesh)で失敗する。

(RayWorkerWrapper pid=1722) ERROR failed to connect, retry=4, retryLimit=3,
  local=[127.0.0.1]:35509, remote=[127.0.1.1]:51638$1,
  error=SO_ERROR: Connection refused

RuntimeError: Gloo connectFullMesh failed with timed out connecting:
  SO_ERROR: Connection refused, remote=[127.0.1.1]:51638$1

原因:Ubuntu/Debian の cloud-init がデフォルトで /etc/hosts127.0.1.1 ホスト名 を書き込む。Gloo はこのエントリを参照して自ノードの IP を 127.0.1.1(ループバック)と判断し、他ノードへ接続しようとして拒否される。

解決策:各ノードの /etc/hosts127.0.1.1 を実際の IP アドレスに修正する。

# GPU-Worker-A で
sudo sed -i 's/127.0.1.1\s*GPU-Worker-A/ GPU-Worker-A/' /etc/hosts

# GPU-Worker-B で
sudo sed -i 's/127.0.1.1\s*GPU-Worker-B/ GPU-Worker-B/' /etc/hosts
補足:本環境では cloud-init(manage_etc_hosts=True)が自動的に実 IP を設定していたため、修正は不要だった。runner コンテナ内の /etc/hosts を直接確認して 127.0.1.1 が存在しないことを確認する。
 

問題 3

Qwen3.5-35B-A3B の Visual Encoder が V100 で動作しない #

Gloo 問題解決後、モデルロードには成功するが profile_run フェーズで即クラッシュ。

File "vllm/model_executor/layers/conv.py", line 236, in _forward_conv
    x = F.conv3d(
        ^^^^^^^^^
RuntimeError: GET was unable to find an engine to execute this computation

原因:Qwen3.5-35B-A3B は Vision Language Model であり、Visual Encoder の Conv3D が V100(compute capability 7.0)向けの cuDNN アルゴリズムを持たない。VLLM_DISABLE_MULTIMODAL=1 等の環境変数では回避不可。vLLM が profile_run 時に必ず Visual Encoder を初期化するため、構造的に動作しない。

解決策:モデルを Qwen2.5-32B-Instruct(テキスト専用)に切り替える。Visual Encoder を持たないため、この問題は発生しない。

 

問題 4

チャット時に /dev/shm 不足で Raylet がクラッシュ #

モデルが起動し、チャットを送信した瞬間にエンジンが落ちる。

WARNING (raylet) store_runner.cc:83: System memory request exceeds memory available in /dev/shm.
  The request is for 10200547328 bytes, and the amount available is 9663676416 bytes.
  If you are inside a Docker container, you may need to pass an argument with the flag '--shm-size'

CUDA error: no kernel image is available for execution on the device

原因:Docker のデフォルト /dev/shm サイズは 64MB。Ray の pipeline_parallel はノード間通信に大量の shared memory を使うため、推論時に枯渇する。gpustack-worker コンテナに --shm-size を指定していなかった。

解決策:gpustack-worker コンテナを --shm-size=16g 付きで再起動する。

docker stop gpustack-worker && docker rm gpustack-worker

docker run -d --name gpustack-worker \
  --restart=unless-stopped \
  --privileged \
  --network=host \
  --shm-size=16g \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume /models:/models \
  --volume /var/lib/gpustack-data:/var/lib/gpustack \
  --runtime nvidia \
  gpustack/gpustack:v2.1.1 \
  --server-url http://<SERVER_IP> \
  --token <TOKEN> \
  --cache-dir /models
注意:GPUStack v2.1.1 の「Mirrored Deployment」機能は gpustack-worker の設定を runner コンテナに引き継ぐが、--shm-size は引き継がれない。これは GPUStack 側の問題であり、後述の環境変数で補完する必要がある。
 

問題 5

runner コンテナ側の shm が引き継がれず RayChannelTimeoutError が継続 #

gpustack-worker の再起動後もチャットで落ちる。

ray.exceptions.RayChannelTimeoutError: System error:
  If the execution is expected to take a long time,
  increase RAY_CGRAPH_get_timeout which is currently 300 seconds.
  Otherwise, this may indicate that the execution is hanging.

原因:vllm/ray の runner コンテナは GPUStack が都度新規作成するため、gpustack-worker の --shm-size 設定はコンテナ間で引き継がれない。runner コンテナ自体の shm が 64MB のまま。

解決策:GPUStack UI のモデル設定 → Environment Variables に以下を追加する。

RAY_CGRAPH_get_timeout=600
RAY_memory_store_capacity=17179869184
 

問題 6

generation_config の repetition_penalty カーネルが V100 非対応でループ出力 #

チャットでテキストが正常に出力されず、記号(♡♡♡…)が無限ループする。または推論中に CUDA カーネルエラーで落ちる。

torch.AcceleratorError: CUDA error: no kernel image is available for execution on the device
# ↑ apply_penalties (repetition_penalty) の実行時に発生

WARNING: Default vLLM sampling parameters have been overridden by the model's
  generation_config.json: {'repetition_penalty': 1.05, 'temperature': 0.7, ...}

原因:Qwen2.5 の generation_config.json に設定された repetition_penalty の CUDA カーネルが V100 向けにコンパイルされていない。

解決策:GPUStack UI のモデル設定 → Backend Parameters に追加:

--generation-config vllm

これでモデルの generation_config.json を無視し、vLLM のデフォルト設定を使用する。

最終的な安定動作設定まとめ #

gpustack-worker 起動コマンド(両ノード共通) #

docker run -d --name gpustack-worker \
  --restart=unless-stopped \
  --privileged \
  --network=host \
  --shm-size=16g \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume /models:/models \
  --volume /var/lib/gpustack-data:/var/lib/gpustack \
  --runtime nvidia \
  gpustack/gpustack:v2.1.1 \
  --server-url http://<SERVER_IP> \
  --token <TOKEN> \
  --cache-dir /models

GPUStack UI モデル設定 #

Backend Parameters:

--tensor-parallel-size 2
--pipeline-parallel-size 2
--distributed-executor-backend ray
--max-model-len 8192
--enforce-eager
--generation-config vllm

Environment Variables:

RAY_CGRAPH_get_timeout=600
RAY_memory_store_capacity=17179869184

動作確認結果 #

Qwen2.5-32B-Instruct (float16) が 4×Tesla V100-PCIE-32GB(2ノード構成)で 16.46 Tokens/s で安定稼働。VRAM 使用率は各 GPU 93〜96%。max-model-len は 8192 トークン。

V100 (compute capability 7.0) 固有の制限事項 #

❌ 動作しないもの #

  • Flash Attention 2(compute 8.0 以上必須)→ Triton ATTN にフォールバック
  • bfloat16(→ float16 に自動変換)
  • Custom AllReduce(NVLink P2P 非対応)
  • SymmMemCommunicator
  • VLM の Conv3D(Qwen3.5-35B-A3B 等)
  • generation_config の repetition_penalty カーネル

✅ 動作するもの #

  • Triton ATTN バックエンド(Flash Attention 代替)
  • NCCL 通信(nccl==2.27.5)
  • Ray 分散実行(pipeline + tensor parallel)
  • torch.compile / CUDA Graphs(enforce-eager で無効化推奨)
  • Qwen2.5 等テキスト専用モデルの推論

トラブルシューティング チェックリスト #

  • ray status(コンテナ内)で全ノードの GPU が認識されているか確認する
  • 各ノードの /etc/hosts でホスト名が 127.0.1.1 ではなく実 IP に解決されることを確認する
  • gpustack-worker コンテナに --shm-size=16g 以上を指定する
  • モデル設定の Environment Variables に RAY_CGRAPH_get_timeout=600RAY_memory_store_capacity=17179869184 を追加する
  • V100 環境では --generation-config vllm を Backend Parameters に追加して generation_config.json を無視する
  • VLM(Vision Language Model)は V100 では動作しない。テキスト専用モデルを使用する
  • V100 では --enforce-eager 追加を検討する(CUDA Graph 関連の不安定さを回避)
  • VRAM が逼迫する場合は --gpu-memory-utilization 0.85 で KV キャッシュ確保量を調整する

参考情報 #

本記事は実環境でのトラブルシューティング記録です。IP・トークン等は抽象化しています。V100 以外の GPU 環境では一部の問題は発生しない場合があります。vLLM および GPUStack のバージョンアップにより状況が変わる可能性があります。

Updated on 2026年4月10日

What are your feelings

  • Happy
  • Normal
  • Sad