全6のデータセンターが正常稼働中

暗号資産で支払い · 本人確認不要 · 5分未満でrootアクセス

実践ガイド・11分で読了

Llama 3.3 70Bを1ノードで提供する

5分前に納品されたマシンから、リクエストに応答するOpenAI互換エンドポイントまで。気づかぬうちにスループットを半減させる2つのフラグと、侵害を招く1つのフラグも解説します。

簡潔な答え

必要なメモリ
4-bitで43 GB、FP8で82 GB、BF16で164 GB — いずれも8kコンテキスト時
最もシンプルなマシン
80 GBカード1枚。シャーディングも、インターコネクトも、同期も不要です
最初のトークンまでの時間
納品から15分足らず。その大半は重みのダウンロードです
ただ一つの誤り
ポート8000をパブリックアドレスに公開すること。認証機能がありません

必要なもの

700億パラメータです。4-bitでは重みが35 GBになり、KVキャッシュは8kコンテキストで1リクエストあたり2.5 GB追加され、実行時のオーバーヘッドは約15%です。それ以外はすべてこの3つの数字から導かれます。詳しくはサイジングガイドをご覧ください。

Llama 3.3 70Bに必要なメモリ(精度・コンテキスト別)
精度重み 8kでの合計32kでの合計128kでの合計
BF16 / FP16リファレンス品質 140 GB 164 GB 173 GB 207 GB
FP8リファレンス設計に近い、HopperおよびBlackwell 70 GB 82 GB 86 GB 103 GB
4-bit (AWQ, GPTQ)最小の重み、キャッシュはFP16のまま 35 GB 43 GB 52 GB 86 GB

128kにおける4-bitの行に注目してください。重みは35 GBまで縮小しますが、キャッシュはまったく縮小しません。AWQとGPTQが量子化するのは重みだけだからです。この一点が、以下のマシン選びの大部分を決めます。

ノードを選ぶ

このモデルを1枚のカードに収められる、当社カタログの中で最も安価なマシンです。可能であればこの構成が望ましいでしょう。シャーディングが不要ということは、同期も不要で、デバッグすべき箇所も1つ減るということです。

Llama 3.3 70Bを1枚のカードに収められるノード
ノード収まる精度カードメモリ推定tok/s月額
NVIDIA RTX A6000PCIe 5.0 · 768 GB/s 4-bit (AWQ, GPTQ) 48 GB ~10 $286/月
2 × NVIDIA RTX A6000PCIe 5.0 ×16 · 768 GB/s 4-bit (AWQ, GPTQ) 48 GB ~10 $597/月
NVIDIA L40SPCIe 5.0 · 864 GB/s 4-bit (AWQ, GPTQ) 48 GB ~11 $714/月
NVIDIA A100 PCIePCIe 5.0 · 1,935 GB/s 4-bit (AWQ, GPTQ) 80 GB ~25 $1,091/月

スループットは単一ストリームの生成速度であり、メモリ帯域幅に制約され、意図的に控えめな数値です。連続バッチ処理を使えば、同時リクエストの合計は数倍に達します。それこそがvLLMの存在意義です。

10分のセットアップ

アドレス以外、ここに当社固有のものはありません。Docker、NVIDIAコンテナツールキット、そして動作するドライバースタックはすでにマシンに用意されています。

マシンを確認し、重みの置き場所を用意する
$ ssh root@203.0.113.42
$ nvidia-smi --query-gpu=name,memory.total --format=csv

# Weights on the fast local NVMe, not the system volume.
$ mkdir -p /scratch/models
$ df -h /scratch

# A gated model needs a token. Skip if yours is open.
$ export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx

サーバーを起動する

コンテナは1つだけです。初回実行時には量子化された重み約40 GBをダウンロードします。1 Gbit/sポートでは数分かかりますが、以降の再起動は数秒で完了します。

vLLM、1枚のカード、4-bit
$ docker run -d --name vllm --restart unless-stopped \
    --gpus all --ipc=host \
    -v /scratch/models:/root/.cache/huggingface \
    -e HF_TOKEN="$HF_TOKEN" \
    -p 127.0.0.1:8000:8000 \
    vllm/vllm-openai:latest \
    --model casperhansen/llama-3.3-70b-instruct-awq \
    --quantization awq_marlin \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.92

# Watch it load. "Application startup complete" is the signal.
$ docker logs -f vllm
最初のリクエスト
$ curl -s http://127.0.0.1:8000/v1/models | head

$ curl -s http://127.0.0.1:8000/v1/chat/completions \
    -H 'Content-Type: application/json' \
    -d '{"model":"casperhansen/llama-3.3-70b-instruct-awq",
         "messages":[{"role":"user","content":"In one sentence: what is a KV cache?"}],
         "max_tokens":80}'

重要なフラグ

--max-model-len実際に提供するコンテキストに合わせて設定するvLLMは宣言された最大値に対してKVキャッシュを確保します。実際には8192しか提供しないのに131072と宣言すると、必要な量の16倍のメモリを無駄にすることになります。しかもその症状はエラーではなく「同時実行数が足りない」という形で現れます。
--gpu-memory-utilization0.90〜0.95vLLMが確保できるカードの割合です。確保しない分はすべて無駄になります。専有マシンで初期値の0.90のままにしておくと、実際の同時実行数を犠牲にすることになります。0.95を超えないようにしてください。
--ipc=host任意ではなく必須これがないと、コンテナの共有メモリは64 MBに制限されます。1枚のカードなら問題にならないこともありますが、シャーディングされたモデルではNCCLが有用なエラーも出さずにハングします。
--tensor-parallel-sizeモデルが収まらない場合に限り1枚のカードに収まるモデルをシャーディングすると、かえって遅くなります。詳しくはインターコネクトガイドをご覧ください。高価なノードが安価なノードより性能で劣る、最もよくある原因です。
--kv-cache-dtype fp8キャッシュが半分になるHopperとBlackwellで利用可能です。保持できるコンテキストまたは同時実行数が2倍になり、品質への影響は通常測定できないほどわずかです。このリストの中で最も手軽に得られる効果です。
--max-num-seqs実際の同時実行数に上限を合わせる8人のユーザーにサービスを提供するマシンで256のままにしておくと、vLLMは256を前提に計画を立て、実際には保持できないリクエストまで受け入れてしまいます。これは拒否ではなく、レイテンシの急上昇として現れます。

世界に公開しないこと

OpenAI互換APIには、初期状態では認証機能がありません。 パブリックアドレスで0.0.0.0にバインドすると、それは公開された推論サーバーとなり、スキャナーは数時間で見つけ出します。上記のコマンドにある-p 127.0.0.1:8000:8000に注目してください。先頭のこのアドレスがインターネットから遮断している要であり、他所からコマンドをコピーする際に最も見落とされやすい一文字です。

ご自身のマシンからSSHトンネル経由でアクセスします。ポートを開く必要も、証明書を管理する必要も、設定を誤る余地もありません。

お使いのノートパソコンから
$ ssh -N -L 8000:127.0.0.1:8000 root@203.0.113.42

# Now http://127.0.0.1:8000 on your laptop is the server.

どうしても公開が必要な場合は、TLSとAPIキーを備えたリバースプロキシを前段に置き、ファイアウォールで送信元アドレスも制限してください。最小限のルールセットはドキュメントに記載されています。誰からの問い合わせにも応答するエンドポイントには、二重三重の備えこそが正しい姿勢です。

スループットを引き上げる

試す価値がある順に並んでいます。最初の2つは無償で行え、通常は最も大きな効果が得られます。

  1. --max-model-lenを実際に使うコンテキストまで下げる。ほとんどの場合、単独では最大の効果があり、実際に使っていたものを失うことはありません。
  2. --gpu-memory-utilizationを0.95まで上げる。これは専有マシンであり、カード上に余地を残しておくべき他のプロセスはありません。
  3. カードが対応していればFP8 KVキャッシュを有効にする。保持できる量が2倍になります。
  4. クライアント側でバッチ処理を行う。連続バッチ処理は、リクエストが同時に到着する場合にのみ効果があります。一件ずつのリクエストでは、どのような設定でもカードの大部分が遊休状態になります。
  5. それでも足りない場合に初めて、より高速なカードを検討する。生成速度はメモリ帯域幅に制約されるため、同じモデルであればH200(4,800 GB/s)はH100 PCIe(2,000)のおよそ2.4×になります。効果は確かにありますが、このリストの中で最も高くつく方法です。
前後を計測し、推測に頼らない
$ docker exec vllm python -m vllm.entrypoints.openai.api_server --help | head -1
$ docker exec vllm vllm bench serve \
    --model casperhansen/llama-3.3-70b-instruct-awq \
    --num-prompts 200 --request-rate 8

# And watch the card while it runs: if utilisation sits below 90%,
# the bottleneck is your client, not the GPU.
$ nvidia-smi dmon -s um

稼働し続けさせる

初日にやっておく価値のある3つのこと。14日目になって気づくと、どれも厄介だからです。

再起動ポリシー

上記のコマンドには--restart unless-stoppedが含まれています。再起動後もコンテナは自動的に復帰し、重みはすでに/scratch上にあるため、1分足らずで起動します。

プロセスではなくカードを監視する

バスから外れたGPUでも、コンテナは正常に見えたままです。ヘルスチェックにnvidia-smi -q -d PERFORMANCEを組み込めば検知できますが、ポートチェックでは検知できません。

重みはバックアップされません

それらはローカルのNVMe上にのみ存在します。再ダウンロードできるので、それ自体は問題ありません。しかし、ファインチューニング済みのアダプターは再ダウンロードできないため、マシンの外のどこかに保管してください。

契約期間が終了すると、猶予期間なしに1時間以内でディスクが消去されます。/scratch上のものもすべて消えます。これは意図的な仕様です。渡されたマシンに他人のデータが残っていないことを保証しているのと同じ約束だからです。ただし、契約最終日はデータの退避を始める日ではないということでもあります。

このモデルを、当社が貸し出すすべてのノードと照合します。

コンフィギュレーターは、どの構成が1枚のカードに収まり、どの構成が分割を要し、それぞれの費用がいくらかを示します。

ログイン

コンソール、請求書、アウトオブバンドアクセス。

アカウントをお持ちでないですか?

個別のサインアップはありません。最初の注文を行う際にアカウントが作成されます。支払いのステップでメールアドレスとパスワードを選択していただき、マシンの用意ができる頃にはコンソールも利用可能になっています。

サーバーを設定

Language