🤖

GPUスパコンでvllmを試してみた:Build wheel from source編

に公開

元にした資料
https://docs.vllm.ai/en/latest/getting_started/installation/gpu.html#build-wheel-from-source

以下、GPUが搭載されたノードグループBまたはCでバッチジョブ実行。ジョブスクリプトのヘッダは省略。(1GPUによる小規模なテスト実行のみのため、資源の空き状況を見て適当に実行。)

Build wheel from sourceを試す

手元でビルドする。
ビルドするためGPUがある環境でやった方が良いと思われる。(CUDAさえ見えていれば大丈夫か?設定オプションがあるか?)

導入1

VER=wheel1
mkdir ${VER}
cd ${VER}

module load cuda/12.8.1
uv venv --python 3.12 --seed
source .venv/bin/activate
git clone https://github.com/vllm-project/vllm.git
cd vllm
VLLM_USE_PRECOMPILED=1 uv pip install --editable .

最初に紹介されているのがこのuv pip install --editable .を使うパターン。
実行してみると、SSL関係のエラーとnumpyのエラーが出る。uv pip install numpyしても、最後のuv pip install--trusted-host系のオプションを追加しても改善せず。
ものは試しでログインノードで実行しても変わらず。(ログインノードで操作するとネットワーク絡みの問題が解決することがある。)
一旦諦め。

  × Failed to build `vllm @
  │ file:///home/pj24001603/ku40000105/work/qwen3/vllm-work/wheel1/vllm`
  ├─▶ The build backend returned an error
  ╰─▶ Call to `setuptools.build_meta.build_editable` failed (exit status: 1)

      [stdout]
      [warn] Falling back to nightly wheel: <urlopen error [SSL:
      CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get
      local issuer certificate (_ssl.c:1010)>
      Downloading wheel from
      https://wheels.vllm.ai/nightly/vllm-1.0.0.dev-cp38-abi3-manylinux1_x86_64.whl
      to
      /tmp/3614168_YnVpbGRfd2hlZWwxLnNoCg==/vllm-wheelsvqa1qotr/vllm-1.0.0.dev-cp38-abi3-manylinux1_x86_64.whl
      Removing temporary directory
      /tmp/3614168_YnVpbGRfd2hlZWwxLnNoCg==/vllm-wheelsvqa1qotr

      [stderr]
      /home/pj24001603/ku40000105/.cache/uv/builds-v0/.tmp5ptPgF/lib/python3.12/site-packages/torch/_subclasses/functional_tensor.py:279:
      UserWarning: Failed to initialize NumPy: No module named 'numpy'
      (Triggered internally at /pytorch/torch/csrc/utils/tensor_numpy.cpp:81.)
        cpu = _conversion_method_template(device=torch.device("cpu"))
      Traceback (most recent call last):
以下略

導入2

VER=wheel2_gcc12
mkdir ${VER}
cd ${VER}

module load cuda/12.8.1 gcc-toolset/12
uv venv --python 3.12 --seed
source .venv/bin/activate
git clone https://github.com/vllm-project/vllm.git
cd vllm
uv pip install -e .
# 以下、ついで
uv pip install -U "huggingface_hub[cli]"
uv pip install -U hf_transfer

CUDAのバージョンはPre-build wheels編と同様に12.8を選択。一度試したらGCC9以降が必要というエラーが発生したため、gcc12が使えるようにmoduleをload。これで無事にビルドできた模様。

後日ビルドし直したら成功しなかった事例あり。git clone時に-b v0.10.1.1を付けたらビルドが成功した。最新コミット版は動かない可能性がある為、安定していそうなバージョンを明示した方が良さそうである。

利用

Simple Profilingを試す

https://docs.vllm.ai/en/latest/examples/offline_inference/simple_profiling.html

サンプルの内容をsimple_profiling.pyに貼り付け、バッチジョブで実行。

VER=wheel2_gcc12
cd ${VER}
module load cuda/12.8.1 gcc-toolset/12
source .venv/bin/activate
uv run ../simple_profiling.py

以下、実行結果の末尾。特にエラーらしいエラーは出ておらず、うまく動いている気がする。

(EngineCore_0 pid=471) Self CPU time total: 1.526s
(EngineCore_0 pid=471) Self CUDA time total: 12.582ms
(EngineCore_0 pid=471)
--------------------------------------------------
Prompt: 'Hello, my name is'
Generated text: ' Joel, my dad is my friend and we are in a relationship. I am'
--------------------------------------------------
Prompt: 'The president of the United States is'
Generated text: ' reportedly being investigated by the FBI over the allegations that he broke campaign finance laws in'
--------------------------------------------------
Prompt: 'The capital of France is'
Generated text: ' all set to open a new gateway to the most notorious terror camps in Europe,'
--------------------------------------------------
Prompt: 'The future of AI is'
Generated text: ' in their hands. We cannot prevent the future.\nAgreed.  '
--------------------------------------------------

なお以下のWARNINGが出ている。uv pip install flashinfer-pythonすれば消える。
Pre-build wheels編ではこれを入れるとserveで躓いた。

(EngineCore_0 pid=471) WARNING 09-05 10:21:38 [topk_topp_sampler.py:69] FlashInfer is not available. Falling back to the PyTorch-native implementation of top-p & top-k sampling. For the best performance, please install FlashInfer.

OpenAI-Compatible Serverを立てる

https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html

今回はバッチジョブ実行でServerを立ててみた。

VER=wheel2_gcc12
cd ${VER}
module load cuda/12.8.1 gcc-toolset/12
source .venv/bin/activate
ifconfig|grep inet
vllm serve NousResearch/Meta-Llama-3-8B-Instruct \
  --dtype auto \
  --api-key token-abc123

IP情報を出力するようにした。
以下は出力の末尾。
特にエラーなくserver起動し、待ち受け状態になったようだ。

(APIServer pid=318) INFO 09-05 10:48:35 [api_server.py:1969] Starting vLLM API server 0 on http://0.0.0.0:8000
省略
(APIServer pid=318) INFO:     Started server process [318]
(APIServer pid=318) INFO:     Waiting for application startup.
(APIServer pid=318) INFO:     Application startup complete.

ログインノードからクライアントを実行。
中身は以下。IPアドレス情報はバッチジョブの出力情報から転記した。


(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ cat ../serve_client_gm.py
from openai import OpenAI
client = OpenAI(
    base_url="http://172.16.17.28:8000/v1",
    api_key="token-abc123",
)

completion = client.chat.completions.create(
    model="NousResearch/Meta-Llama-3-8B-Instruct",
    messages=[
        {"role": "user", "content": "Good morning!"}
    ]
)

print(completion.choices[0].message)
(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ cat ../serve_client_hello.py
from openai import OpenAI
client = OpenAI(
    base_url="http://172.16.17.28:8000/v1",
    api_key="token-abc123",
)

completion = client.chat.completions.create(
    model="NousResearch/Meta-Llama-3-8B-Instruct",
    messages=[
        {"role": "user", "content": "Hello!"}
    ]
)

print(completion.choices[0].message)

実行時の出力。

(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ uv run ../serve_client_gm.py
ChatCompletionMessage(content="Good morning! I hope you're having a great start to your day. How can I help you today?", refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[], reasoning_content=None)
(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ uv run ../serve_client_hello.py
ChatCompletionMessage(content="Hello! It's nice to meet you. Is there something I can help you with, or would you like to chat?", refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[], reasoning_content=None)

サーバ側の出力。

(APIServer pid=318) INFO 09-05 10:52:15 [chat_utils.py:507] Detected the chat template content format to be 'string'. You can set `--chat-template-content-format` to override this.
(APIServer pid=318) INFO:     172.16.0.2:46402 - "POST /v1/chat/completions HTTP/1.1" 200 OK
(APIServer pid=318) INFO 09-05 10:52:26 [loggers.py:123] Engine 000: Avg prompt throughput: 1.3 tokens/s, Avg generation throughput: 2.3 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
(APIServer pid=318) INFO:     172.16.0.2:34578 - "POST /v1/chat/completions HTTP/1.1" 200 OK
(APIServer pid=318) INFO 09-05 10:52:36 [loggers.py:123] Engine 000: Avg prompt throughput: 1.2 tokens/s, Avg generation throughput: 2.6 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%

どうやらうまく動いてくれたようだ。

Qwen3-Coderで遊んでみる

流行のQwen3-Coderを動かしてみる。

https://docs.vllm.ai/projects/recipes/en/latest/Qwen/Qwen3-Coder-480B-A35B.html

とりあえずFP8 Modelをmax-model-len=100にして、資源節約試験実行。
H100 94GiB版を4GPU搭載したノードグループBを1ノード使用。

VER=wheel2_gcc12
cd ${VER}
module load cuda/12.8.1 gcc-toolset/12
source .venv/bin/activate
ifconfig|grep inet
VLLM_USE_DEEP_GEMM=1 vllm serve Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8 \
  --max-model-len 100 \
  --enable-expert-parallel \
  --data-parallel-size 4 \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder

バッチジョブ実行してみたところ、いくつかWARNINGなどが見えるが(重複しているもの、長いものは省略している)、待ち受け状態にはなってくれた。

(APIServer pid=318) WARNING 09-05 11:18:48 [_ipex_ops.py:16] Import error msg: No module named 'intel_extension_for_pytorch'
[W905 11:19:16.011937364 ProcessGroupNCCL.cpp:981] Warning: TORCH_NCCL_AVOID_RECORD_STREAMS is the default now, this environment variable is thus deprecated. (function operator())
(EngineCore_3 pid=606) WARNING 09-05 11:19:23 [fp8.py:540] Failed to import DeepGemm kernels.
(EngineCore_3 pid=606) WARNING 09-05 11:19:23 [fp8.py:563] CutlassBlockScaledGroupedGemm not supported on the current platform.
(EngineCore_0 pid=603) WARNING 09-05 11:21:04 [fused_moe.py:727] Using default MoE config. Performance might be sub-optimal! Config file not found at ['/home/pj24001603/ku40000105/work/qwen3/vllm-work/wheel2_gcc12/vllm/vllm/model_executor/layers/fused_moe/configs/E=32,N=768,device_name=NVIDIA_H100,dtype=fp8_w8a8,block_shape=[128,128].json']
(APIServer pid=318) WARNING 09-05 11:21:30 [__init__.py:1686] Default sampling parameters have been overridden by the model's Hugging Face generation config recommended from the model creator. If this is not intended, please relaunch vLLM instance with `--generation-config vllm`.

ログインノードから、試しに簡単な質問を投げてみた。
C言語のHellow, worldについて質問。
(そんなの計算資源を費やして聞くなという話である(笑))

(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ cat ../serve_client_code1.py
from openai import OpenAI
client = OpenAI(
    base_url="http://172.16.17.7:8000/v1",
    api_key="token-abc123",
)

completion = client.chat.completions.create(
    model="Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8",
    messages=[
        {"role": "user", "content": "C言語のHello, worldプログラムを教えて!"}
    ]
)

print(completion.choices[0].message)
(wheel2_gcc12) [ku40000105@genkai0002 wheel2_gcc12]$ uv run ../serve_client_code1.py
ChatCompletionMessage(content='もちろん!以下は C 言語で「Hello, World!」と表示する基本的なプログラムです。\n\n```c\n#include <stdio.h>\n\nint main() {\n    printf("Hello, World!\\n");\n    return 0;\n}\n```\n\n### 解説:\n1. `#include <stdio.h>`  \n   - `stdio.h` は標準入出力を行う', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[], reasoning_content=None)

うまく動いているようだ。
(実はこれでQwen3-Coderを初めて使った。)

参考までにサーバ側のログ。

(APIServer pid=318) INFO:     Started server process [318]
(APIServer pid=318) INFO:     Waiting for application startup.
(APIServer pid=318) INFO:     Application startup complete.
(APIServer pid=318) INFO 09-05 11:25:39 [chat_utils.py:507] Detected the chat template content format to be 'string'. You can set `--chat-template-content-format` to override this.
(APIServer pid=318) INFO:     172.16.0.2:39108 - "POST /v1/chat/completions HTTP/1.1" 200 OK
(APIServer pid=318) INFO 09-05 11:25:51 [loggers.py:123] Engine 000: Avg prompt throughput: 4.0 tokens/s, Avg generation throughput: 6.0 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
(APIServer pid=318) INFO 09-05 11:26:01 [loggers.py:123] Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
(APIServer pid=318) INFO:     172.16.0.2:49132 - "POST /v1/chat/completions HTTP/1.1" 200 OK
(APIServer pid=318) INFO 09-05 11:26:41 [loggers.py:123] Engine 000: Avg prompt throughput: 1.9 tokens/s, Avg generation throughput: 8.1 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
(APIServer pid=318) INFO 09-05 11:26:51 [loggers.py:123] Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%

DeepGemmを追加インストールしてみた。

https://github.com/deepseek-ai/DeepGEMM

ログインノードでgit cloneしておいて、計算ノードでdevelop.shinstall.shを実行。 uv環境のため、install.shはそのまま実行せずにpython setup.py bdist_wheeluv pip install dist/*.whl`を実行したが、意味があるのかは不明。
DeepGemmのWARNINGは消えたが、最後に以下のWARNINGが出るようになったため、cuda12.9でも試してみる予定。

Warning: please use at least NVCC 12.9 for the best DeepGEMM performance

FP16版でも同様に動くことを確認した。

480Bのような大きなモデルや、---max-model-lenを大きくしたものでも動作するかは引き続き確認する予定。

Discussion