DGX Spark を2台連結するとNCCLという仕組みで、単体では載らない巨大LLM(Llama-3.1-405B、Qwen3-235Bなど)を動かせるという技術です。仕組みがよくわからなかったので、セットアップしながら勉強したメモ。
NCCLとは
NVIDIA Collective Communication Library で「NVIDIAのGPU同士で超高速にデータをやり取りするためのライブラリ」 です。CPUを経由せず、GPUメモリから直接NIC(ネットワークカード)に転送する仕組み(RDMA)で、DGX SparkのConnectX-7チップを使い 200Gbps(= 約25GB/s)でデータをやり取りします。
ポイント
- CPUを経由せず、GPUメモリから直接NICに転送する仕組み(RDMA)
- ソフト自体がNCCL対応している必要がある
- 対応: PyTorch、vLLM、TensorRT-LLM、DeepSpeed
- 非対応: LM Studio、Ollama(マルチノード不可)
速さの仕組み
1. RDMA(CPUバイパス)
普通のTCP通信:
GPU → CPUメモリ → OSカーネル → NIC → ネットワーク
↑ コピーとCPU処理がボトルネック
NCCL + RDMA:
GPU ──→ NIC → ネットワーク
↑ CPUもOSもスキップ
2. コレクティブ通信アルゴリズム
NCCLは単純な1対1転送ではなく、Ring AllReduce や Tree AllReduce といったアルゴリズムを使い分けます。例えばN台のGPUでAllReduceする際、Ring型だとデータを分割してリング状に流すことで、ノード数が増えても通信量が線形に増えない設計になっています。
3. トポロジー認識
NCCLが起動時に「どのGPUがどのNICに繋がってるか」を自動検出し、最適なルートを選択。ユーザーが手動で設定する必要はほぼありません。
インストール
ここを参考にしました。
- 2台をQSFP/CX7ケーブルで接続(1万円くらい)
-
netplan設定ファイルをダウンロードして適用 -
./discover-sparksでDGX Sparkを探して、SSHキーで2台にログインできるように設定(同じユーザー) - NCCLをビルド、インストール。Blackwell (sm_121) 対応のためにソースビルド
- 環境変数を設定
IPアドレス確認:
ip -brief address show
ポイント
- 2台で同じ設定 & ビルド/インストールをする必要がある
- 2台に同じユーザーアカウントが必要(mpirunがSSH経由でリモートプロセスを起動するため)
- 環境変数は
~/.bashrcで設定するとユーザー個別。全員で共有するなら/etc/profile.d/nccl.sh
環境変数の例
export NCCL_HOME=/usr/local/nccl
export LD_LIBRARY_PATH=$NCCL_HOME/lib:$LD_LIBRARY_PATH
export NCCL_SOCKET_IFNAME=enp1s0f1np1 # CX-7インターフェース
ハマりどころ: DGX Sparkでは物理ポートが enp1s0f1np1 と enP2p1s0f1np1 のように2つの名前で見えることがあります。NCCL設定では enp1... の方を使うのが推奨。
動作確認(nccl-tests)
セットアップ後は公式の nccl-tests でベンチマーク確認:
mpirun --allow-run-as-root -np 2 \
-H 192.168.100.10:1,192.168.100.11:1 \
./build/all_reduce_perf -b 8 -e 256M -f 2 -g 1
結果の見方:
- algbw (algorithmic bandwidth):アルゴリズム上の帯域
- busbw (bus bandwidth):実際の物理帯域 ← こっちが重要
- busbw が物理リンク(200Gbps = 25GB/s)に近づいていればOK
デバッグ用環境変数
通信がうまくいかないときは:
export NCCL_DEBUG=INFO
を設定すると、どのインターフェース・どのアルゴリズムを使ってるか詳細ログが出ます。
PyTorchで使うには(例)
import torch
import torch.distributed as dist
# NCCLバックエンドで初期化
dist.init_process_group(backend="nccl")
# あとは普通にPyTorchを書く
tensor = torch.ones(10).cuda()
dist.all_reduce(tensor) # 裏でNCCLが動く
起動方法
torchrun --nnodes=2 --nproc_per_node=1 \
--master_addr=192.168.100.10 --master_port=29500 \
train.py
vLLMの場合
LLM推論なら vLLM が楽。設定ファイルに書くだけでNCCLを意識しなくてOK:
vllm serve meta-llama/Llama-3.1-405B \
--tensor-parallel-size 2 \
--distributed-executor-backend ray
役割
| 技術 | 役割 |
|---|---|
| SSH | リモートでプロセスを起動する「入口」 |
| MPI | 複数プロセスの起動と協調(bootstrap) |
| NCCL | GPU間の高速データ転送本体 |
SSHでプロセス起動 → MPIで協調 → NCCLでGPU間データ転送、という流れ。
並列化の種類
2台で動かす際には、モデルの分割方法を選ぶ必要があります:
- テンソル並列 (TP):層の中の計算を分割。通信量多いが低遅延が必要。200Gbpsの高速リンクが活きる
- パイプライン並列 (PP):層ごとに分割。通信量は少ないがGPU遊休時間が発生
- データ並列 (DP):同じモデルを複数GPUに置いて別データを処理。学習時に使用
DGX Spark 2台では主に TP=2 で使うケースが多い...らしい
メモ(ハマりどころ・注意点)
- 対応しているのは PyTorch、vLLM、TensorRT-LLM、DeepSpeedなど
- LM Studio、Ollamaはシングルノード前提なので2台連結不可
- ログイン(実行)アカウントでお互いにプロセスを立ち上げて連携する
- 2台のメモリを合算して大きなモデルを載せられるようになるだけで、1台で収まるモデルを高速化するものではない(むしろ通信オーバーヘッドで遅くなる)
- NCCLビルド時は
NVCC_GENCODE="-gencode=arch=compute_121,code=sm_121"を忘れずに(Blackwell対応) - aptで入るNCCLはsm_121最適化されていない可能性があるのでソースビルド推奨