diff --git a/docs/dgx-spark-dual/index.md b/docs/dgx-spark-dual/index.md new file mode 100644 index 0000000..7060324 --- /dev/null +++ b/docs/dgx-spark-dual/index.md @@ -0,0 +1,444 @@ +--- +sidebar_position: 3 +title: DGX Spark デュアル構成ガイド +description: 2台のDGX Sparkを接続して256GBメモリ環境を構築する方法を初心者向けに解説 +--- + +# DGX Spark デュアル構成ガイド + +2台のDGX Sparkを接続して、**256GBの巨大メモリ環境**を構築する方法を解説します。 + +## はじめに + +### この記事で学べること + +- 2台のDGX Sparkを接続する方法 +- ネットワーク設定の仕組み +- vLLMクラスターの起動方法 + +### 対象読者 + +- DGX Sparkを2台持っている方 +- 70B〜405Bの大規模モデルを動かしたい方 +- Linuxの基本操作ができる方 + +### 前提条件 + +- DGX Spark × 2台 +- QSFPケーブル × 1本 +- 両方のマシンに同じユーザー名でログインできる + +--- + +## なぜデュアル構成が必要? + +DGX Spark 1台のメモリは **128GB** です。 + +| 構成 | メモリ | 動かせるモデル | +|------|--------|---------------| +| 単体 | 128GB | 〜70B(量子化時) | +| **デュアル** | **256GB** | 〜405B | + +**Llama-3.3-70B** や **MiniMax-M2.5-172B** など、大きなモデルを動かすにはデュアル構成が必要です。 + +--- + +## 全体像 + +まず、完成形のイメージを掴みましょう。 + +``` +┌─────────────────────┐ ┌─────────────────────┐ +│ │ │ │ +│ DGX Spark 1 │ │ DGX Spark 2 │ +│ (ヘッドノード) │ │ (ワーカーノード) │ +│ │ │ │ +│ ┌───────────────┐ │ QSFPケーブル │ ┌───────────────┐ │ +│ │ 192.168.100.10│◄─┼─────────────────────────┼─►│ 192.168.100.11│ │ +│ │ (QSFP) │ │ 200Gbps │ │ (QSFP) │ │ +│ └───────────────┘ │ │ └───────────────┘ │ +│ │ │ │ +│ ┌───────────────┐ │ │ ┌───────────────┐ │ +│ │ 10.0.0.10 │ │ 通常のLAN │ │ 10.0.0.11 │ │ +│ │ (eth0) │◄─┼─────────────────────────┼─►│ (eth0) │ │ +│ └───────────────┘ │ │ └───────────────┘ │ +│ │ │ │ +└─────────────────────┘ └─────────────────────┘ + │ + │ API (ポート8000) + ▼ + クライアント +``` + +**ポイント**: +- **QSFPケーブル**:2台のSparkを直接つなぐ超高速回線(200Gbps) +- **通常LAN**:普段使っているネットワーク(SSH接続、API公開用) + +--- + +## 手順1:物理接続 + +### ケーブルを差す + +両方のDGX Sparkの **QSFPポート** にケーブルを差すだけ! + +``` + DGX Spark 1 DGX Spark 2 + ┌───────────┐ ┌───────────┐ + │ [QSFP]───┼──────────────┼───[QSFP] │ + │ │ ケーブル1本 │ │ + └───────────┘ └───────────┘ +``` + +:::tip QSFPポートの場所 +背面にある大きめのポートです。LANケーブルより太いケーブルが刺さります。 +::: + +### 接続確認 + +どちらかのマシンで以下を実行: + +```bash +ibdev2netdev +``` + +出力例: +``` +mlx5_0 port 1 ==> enp1s0f1np1 (Up) ← ✅ Upになっていれば接続OK +mlx5_1 port 1 ==> enp1s0f0np0 (Down) +``` + +:::warning Upにならない場合 +- ケーブルがしっかり刺さっているか確認 +- 両方のマシンでコマンドを実行して確認 +::: + +--- + +## 手順2:ネットワーク設定 + +QSFPポートには **IPアドレスが自動で割り当てられません**。手動で設定が必要です。 + +### 設計を決める + +| マシン | QSFPのIP | 役割 | +|--------|---------|------| +| Spark 1 | 192.168.100.10 | ヘッドノード | +| Spark 2 | 192.168.100.11 | ワーカーノード | + +:::tip IPアドレスの決め方 +`192.168.100.x` は例です。既存のネットワークと被らなければOK。 +::: + +### Spark 1 で設定 + +```bash +# 一時的に設定(再起動で消える) +sudo ip addr add 192.168.100.10/24 dev enp1s0f1np1 +sudo ip link set enp1s0f1np1 up +``` + +### Spark 2 で設定 + +```bash +# 一時的に設定(再起動で消える) +sudo ip addr add 192.168.100.11/24 dev enp1s0f1np1 +sudo ip link set enp1s0f1np1 up +``` + +### 疎通確認 + +Spark 1 から Spark 2 に ping: + +```bash +ping 192.168.100.11 +``` + +``` +PING 192.168.100.11 (192.168.100.11) 56(84) bytes of data. +64 bytes from 192.168.100.11: icmp_seq=1 ttl=64 time=0.123 ms ← ✅ 成功! +``` + +### 永続化(再起動しても消えないように) + +設定を永続化するには、netplanファイルを作成します。 + +**Spark 1:** +```bash +sudo tee /etc/netplan/99-qsfp.yaml << 'EOF' +network: + version: 2 + ethernets: + enp1s0f1np1: + addresses: + - 192.168.100.10/24 +EOF + +sudo netplan apply +``` + +**Spark 2:** +```bash +sudo tee /etc/netplan/99-qsfp.yaml << 'EOF' +network: + version: 2 + ethernets: + enp1s0f1np1: + addresses: + - 192.168.100.11/24 +EOF + +sudo netplan apply +``` + +--- + +## 手順3:SSH設定 + +2台のマシン間で **パスワードなしでSSH接続** できるようにします。 + +### なぜ必要? + +vLLMクラスターが内部で自動的にSSH接続を使うためです。 + +### Spark 1 → Spark 2 + +Spark 1 で実行: + +```bash +# 鍵がなければ作成 +ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 + +# Spark 2 に公開鍵をコピー +ssh-copy-id $USER@192.168.100.11 +``` + +確認: +```bash +ssh 192.168.100.11 "hostname" +``` +パスワードなしで `spark2`(ホスト名)が表示されればOK! + +### Spark 2 → Spark 1 + +Spark 2 で実行: + +```bash +ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 +ssh-copy-id $USER@192.168.100.10 +``` + +確認: +```bash +ssh 192.168.100.10 "hostname" +``` + +--- + +## 手順4:vLLMクラスター起動 + +いよいよ本番!2台を1つのクラスターとして動かします。 + +### 4-1. 両方のマシンで準備 + +**両方のマシンで実行:** + +```bash +# vLLMイメージを取得 +docker pull nvcr.io/nvidia/vllm:25.11-py3 + +# クラスター起動スクリプトを取得 +wget https://raw.githubusercontent.com/vllm-project/vllm/refs/heads/main/examples/online_serving/run_cluster.sh +chmod +x run_cluster.sh +``` + +### 4-2. ヘッドノード起動(Spark 1) + +Spark 1 で実行: + +```bash +# 環境変数を設定 +export VLLM_IMAGE=nvcr.io/nvidia/vllm:25.11-py3 +export MN_IF_NAME=enp1s0f1np1 +export VLLM_HOST_IP=192.168.100.10 + +# ヘッドノードとして起動 +bash run_cluster.sh $VLLM_IMAGE $VLLM_HOST_IP --head ~/.cache/huggingface \ + -e VLLM_HOST_IP=$VLLM_HOST_IP \ + -e NCCL_SOCKET_IFNAME=$MN_IF_NAME \ + -e GLOO_SOCKET_IFNAME=$MN_IF_NAME \ + -e RAY_memory_monitor_refresh_ms=0 +``` + +:::tip 起動を待つ +`Ray runtime started.` と表示されるまで待ちます(1〜2分) +::: + +### 4-3. ワーカーノード起動(Spark 2) + +Spark 2 で実行: + +```bash +# 環境変数を設定 +export VLLM_IMAGE=nvcr.io/nvidia/vllm:25.11-py3 +export MN_IF_NAME=enp1s0f1np1 +export VLLM_HOST_IP=192.168.100.11 +export HEAD_NODE_IP=192.168.100.10 # ← Spark 1 のIP + +# ワーカーノードとして起動 +bash run_cluster.sh $VLLM_IMAGE $HEAD_NODE_IP --worker ~/.cache/huggingface \ + -e VLLM_HOST_IP=$VLLM_HOST_IP \ + -e NCCL_SOCKET_IFNAME=$MN_IF_NAME \ + -e GLOO_SOCKET_IFNAME=$MN_IF_NAME \ + -e RAY_memory_monitor_refresh_ms=0 +``` + +### 4-4. クラスター確認 + +Spark 1 で実行: + +```bash +# コンテナ名を取得 +export VLLM_CONTAINER=$(docker ps --format '{{.Names}}' | grep -E '^node-[0-9]+$') + +# Rayクラスターの状態を確認 +docker exec $VLLM_CONTAINER ray status +``` + +期待する出力: +``` +Healthy: + 2 node(s) ← ✅ 2ノードになっていれば成功! +``` + +--- + +## 手順5:モデルを起動 + +クラスターができたら、大規模モデルを起動します。 + +### MiniMax-M2.5-172B を起動する例 + +Spark 1(ヘッドノード)で実行: + +```bash +docker exec -it $VLLM_CONTAINER /bin/bash -c ' + vllm serve MiniMax-AI/MiniMax-M2.5-REAP-172B-A10B \ + --tensor-parallel-size 2 \ + --trust-remote-code \ + --max-model-len 8192 \ + --host 0.0.0.0 \ + --port 8000' +``` + +| オプション | 意味 | +|-----------|------| +| `--tensor-parallel-size 2` | 2台のGPUに分散 | +| `--host 0.0.0.0` | 外部からアクセス可能に | +| `--max-model-len 8192` | 最大コンテキスト長 | + +:::warning 起動に時間がかかります +モデルのダウンロード(初回のみ)と読み込みで **10〜30分** かかることがあります。 +::: + +--- + +## 手順6:動作確認 + +### APIにリクエストを送る + +別のターミナル(または別のPC)から: + +```bash +curl http://:8000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "MiniMax-AI/MiniMax-M2.5-REAP-172B-A10B", + "messages": [{"role": "user", "content": "こんにちは!"}] + }' +``` + +レスポンスが返ってくれば成功!🎉 + +--- + +## ワンライナーで簡単セットアップ + +上記の手順を自動化するスクリプトを用意しています。 + +```bash +# フルセットアップ +curl -sL https://docs.techswan.online/scripts/dgx-spark-setup.sh | bash -s -- all +``` + +| コマンド | 内容 | +|----------|------| +| `network` | QSFPのIP設定 | +| `ssh` | SSH鍵配布 | +| `docker` | Docker権限設定 | +| `vllm-pull` | vLLMイメージ取得 | +| `cluster` | クラスター起動 | +| `all` | 全部実行 | + +--- + +## トラブルシューティング + +### pingが通らない + +**症状**:`ping 192.168.100.11` がタイムアウト + +**対処**: +1. ケーブルが正しく接続されているか確認 +2. `ibdev2netdev` で `Up` になっているか確認 +3. IPアドレスが正しく設定されているか確認: + ```bash + ip addr show enp1s0f1np1 + ``` + +### Rayクラスターが1ノードのまま + +**症状**:`ray status` で `1 node(s)` と表示される + +**対処**: +1. ワーカーノードでSSH接続テスト +2. ワーカー側のコンテナログを確認: + ```bash + docker logs $(docker ps -q) + ``` + +### vLLMがOOMで落ちる + +**症状**:Out of Memory エラー + +**対処**: +```bash +# max-model-len を小さくする +vllm serve --tensor-parallel-size 2 --max-model-len 4096 +``` + +--- + +## まとめ + +| 手順 | 内容 | +|------|------| +| 1 | QSFPケーブルで2台を接続 | +| 2 | QSFPポートにIPアドレスを設定 | +| 3 | パスワードなしSSHを設定 | +| 4 | vLLMクラスターを起動 | +| 5 | 大規模モデルを起動 | + +これで **256GB環境** が手に入りました!🎉 + +--- + +## 参考リンク + +- [NVIDIA DGX Spark Playbooks](https://build.nvidia.com/spark/) +- [vLLM ドキュメント](https://docs.vllm.ai/) +- [DGX SparkでMiniMax-M2.5を動かす](/dgx-spark-minimax/) + +--- + +*この記事は2026年2月時点の情報です。最新情報は公式ドキュメントをご確認ください。* diff --git a/docs/index.md b/docs/index.md index ba0354b..1e0d3aa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,14 +13,18 @@ AI・インフラ・開発の技術メモ ### DGX Spark - [DGX SparkでMiniMax-M2.5-REAP-172Bを動かす](/dgx-spark-minimax/) +- [DGX Spark デュアル構成ガイド](/dgx-spark-dual/) 🆕 ## スクリプト 記事で紹介しているスクリプトはダウンロードして使用できます。 ```bash -# DGX Spark セットアップ +# DGX Spark セットアップ(デュアル構成) curl -sL https://docs.techswan.online/scripts/dgx-spark-setup.sh | bash -s -- all + +# モデル起動 +curl -sL https://docs.techswan.online/scripts/dgx-spark-serve.sh | bash -s -- minimax-m25 ``` ## リンク diff --git a/sidebars.ts b/sidebars.ts index 59d59d1..6804074 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -7,6 +7,7 @@ const sidebars: SidebarsConfig = { label: 'DGX Spark', items: [ 'dgx-spark-minimax/index', + 'dgx-spark-dual/index', ], }, ],