メインコンテンツへ移動
AIチュートリアル

2台のNVIDIA DGX SparkシステムでGLM-5.3 Flash EXL3をサーブする

2台のNVIDIA GB10 DGX SparkシステムでGLM-5.3 Flash EXL3をインストール、設定、起動、テスト、チューニングする方法を解説します。2ノードランタイム、DFlash2投機的デコーディング、fp8 MLA KVキャッシュ、OpenAI互換リクエスト、プレフィックスキャッシュ、ベンチマーク、オプションのアブレーション、重要な設定上の制約を取り上げます。

2台のNVIDIA DGX SparkでGLM-5.3 Flash EXL3をサーブ

概要

2台のDGX Spark向けGLM-5.3 Flash EXL3は、2台のNVIDIA GB10システムにまたがってGLM-5.3 Flashの4 bpw EXL3/TR3量子化版を提供するためのデプロイレシピおよびvLLMオーバーレイです。ポート8888でOpenAI互換APIを公開し、モデル識別子GLM-5.3-Flash-EXL3としてモデルを提供します。

このレシピでは、各マシンに1ランクを割り当てたテンソル並列処理を使用します。パック済みEXL3ルーテッドエキスパート、ネイティブsm_121aカーネル、fp8 sparse-MLA KVキャッシュ、CUDAグラフ、および7個のドラフトトークンを用いるDFlash2投機的デコーディングを組み合わせています。

デフォルトで使用されるチェックポイントはMia-AiLab/GLM-5.3-Flash-EXL3-TR3-4bpwです。これは、参照されているBrandon Musicのスナップショットとバイト単位で同一の公開ミラーです。120個のシャードに約164 GiBが含まれています。モデルリポジトリには独自のライセンスがあり、サービングスクリプトとオーバーレイはMITライセンスです。

オーバーレイが必要な理由

標準のARM64 GLM-5.3 vLLMイメージはこのチェックポイントを読み込めますが、GLM-5.3 FlashがNoPE MLAを使用する一方で、利用可能なSM12x sparse-MLAバックエンドが異なるパック形状を要求するため、最初のフォワードパスで失敗します。このオーバーレイは、QK内積を変更せずに、512次元のNoPE潜在表現をFLASHINFER_MLA_SPARSE_SM120に必要な形状へパディングします。

また、機能するEXL3量子化方式も登録します。これにより、ルーテッドエキスパートはBF16へ展開されず、パック済みのtrellis、SUH、SVH、MCG表現のまま保持されます。融合パスを有効にすると、各層でexllamav3_ext.exl3_moeの起動を1回だけ使用します。

さらにこのオーバーレイは、EAGLE3の補助隠れ状態キャプチャ、ターゲットMLA KVスロットを共有するドラフトのスライディングウィンドウアテンション、投機的ドラフトブロック内の非因果アテンションなど、DFlash2向けのGLM固有の統合機能を提供します。

主な機能

  • OpenAI互換サービス: vLLMはヘッドノード上で/v1/chat/completionsおよび関連エンドポイントを公開します。
  • 2ノードのテンソル並列処理: デプロイでは--nnodes 2と--tensor-parallel-size 2を使用します。
  • コンパクトなEXL3重み: 4 bpwチェックポイントのダウンロード容量は約164 GiBで、参照されている品質パネルでは176 GBと報告されています。
  • DFlash2投機的デコーディング: デフォルトのドラフトモデルはincoai/GLM-5.3-Flash-DFlash2で、k=7を使用します。
  • 長いコンテキスト: デフォルトの最大モデル長は900,000トークンで、記載されたメモリ構成ではfp8 MLAプールにより982,612トークンまで対応すると報告されています。
  • マルチモーダル対応: 画像と動画の入力が有効で、プロンプトごとのデフォルト上限は画像4枚、動画1本です。
  • ツールおよび推論のパース: ランチャーは自動ツール選択と、GLM互換のツール呼び出しおよび推論パーサーを有効にします。
  • プレフィックスキャッシュ: 関連するハッシュがキャッシュに残っている場合、ブロック境界に整列したプレフィックスを再利用できます。
  • 拒否方向アブレーション(オプション): ABLIT=1を指定すると、ロード時に選択されたネイティブBF16出力射影重みにメモリ内編集を適用します。

ハードウェアおよびソフトウェア要件

このレシピは、記載されたCX7ファブリックで接続された2台のNVIDIA GB10 DGX Sparkクラスシステム向けに特別に設計されています。汎用的な単一GPUデプロイメントではありません。

  • 初期セットアップ用に各ノード約180 GiBの空きストレージを備えた2台のNVIDIA GB10システム。
  • 両システムでsudoなしに利用できるDocker。
  • ヘッドノードからワーカーへのパスワードなしSSH。
  • ヘッドノードにインストールされたhfまたはhuggingface-cli、curl、rsync。
  • 両マシンにおける正しいCX7ネットワークインターフェースとRDMAデバイス。
  • 120シャードのチェックポイントと約2.3 GiBのDFlash2モデルを保持できるHugging Faceキャッシュ場所。

物理的な配線が異なる場合を除き、リポジトリのCX7インターフェース設定とHCA設定をそのまま使用してください。READMEでは、NCCLが10.0.0.xループバックエイリアスを使用できず、ファブリックのピン設定が正しくない場合にncclCommInitRank中にハングする可能性があると警告しています。

デプロイメントのインストールと設定

1. リポジトリをクローンする

git clone https://github.com/MiaAI-Lab/GLM-5.3-Flash-EXL3-2x-DGX-Sparks.git
cd GLM-5.3-Flash-EXL3-2x-DGX-Sparks

2. 環境ファイルを作成する

cp .env.example .env

マシンがレシピのデフォルトアドレスやアカウント名を使用していない場合は、.envを編集してください。特に重要な設定は次のとおりです。

  • ヘッドノードとvLLMマスターのHEAD_IP=10.0.0.1。
  • 2台目のSparkのWORKER_IP=10.0.0.2。
  • ノード間でSSHアカウントが異なる場合のWORKER_USER。
  • ワーカーのホームディレクトリまたはHugging Faceキャッシュ場所が異なる場合のWORKER_HOME。
  • APIリスナーのPORT=8888。

ランチャーは.envがない場合、.env.exampleから自動的に作成します。コマンドの前に直接指定した値は、ファイル内の値より優先されます。

3. 必要に応じて重みを事前配置する

./download.sh

このコマンドは、EXL3チェックポイントとDFlash2モデルをヘッドノードのHugging Faceキャッシュにダウンロードします。Dockerの実行、ワーカーへの接続、ファイルの同期は行いません。ワーカーの準備が整う前に約164 GiBのモデルのダウンロードを完了させたい場合に使用してください。

キャッシュ済みファイルを明示的に更新するには、次を実行します。

REFRESH_WEIGHTS=1 ./download.sh

不要な再読み込みは避けてください。download.sh と start.sh は、すでに完了しているリポジトリをスキップします。

4. 両方のランクと API を起動する

./start.sh

起動スクリプトは次の順序で処理を実行します。

  1. 両ノードで Docker、SSH、利用可能なディスク容量を確認します。
  2. head で公開イメージ ghcr.io/miaai-lab/glm-5.3-flash-2x-dgx-sparks:exl3 を取得します。
  3. ダイジェストが変更されている場合、コンテナイメージを worker に転送します。
  4. 不足しているモデルファイルを head の Hugging Face キャッシュにダウンロードします。
  5. rsync でキャッシュを worker に同期します。
  6. worker で rank 1 をヘッドレスモードで起動します。
  7. head で rank 0 と OpenAI 互換 API を起動します。
  8. モデルの読み込みとウォームアップが完了するまで、ヘルスエンドポイントをポーリングします。

デフォルトの準備完了タイムアウトは 3,600 秒です。重みの読み込みと CUDA グラフのキャプチャには、かなりの時間がかかる場合があるためです。

5. ステータスとログを確認する

./start.sh status
./start.sh logs
./start.sh logs worker

次のコマンドで両方のコンテナを停止します。

./start.sh stop

./stop.sh も使用できます。

基本的なチャットリクエストを送信する

head ノードでは、ベース API URL は http://127.0.0.1:8888/v1 です。記載されている LAN アドレスを使えば、他のマシンから http://10.0.0.1:8888/v1 を使用できます。

curl -s http://127.0.0.1:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "GLM-5.3-Flash-EXL3",
    "messages": [
      {"role": "user", "content": "テンソル並列処理について簡単に説明してください。"}
    ],
    "chat_template_kwargs": {
      "enable_thinking": false
    }
  }'

リクエストの model 値は、提供されているモデル名と一致している必要があります。デフォルトは GLM-5.3-Flash-EXL3 です。Thinking はデフォルトで有効です。無効にするには、上記のように JSON リクエストのトップレベルに chat_template_kwargs を配置します。

raw HTTP で、リテラルなネストされた extra_body オブジェクトを送信しないでください。OpenAI Python SDK では、extra_body は SDK のオプションであり、その内容はトップレベルのリクエストにマージされます。

チェックポイントの生成設定によっては、temperature=1.0 と top_p=0.95 が指定される場合があります。異なる動作が必要な場合は、各リクエストでサンプリング値を設定してください。

デフォルトのランタイムを理解する

このデプロイメントのデフォルト値は、意図的に連携するよう調整されています。1 つのコンポーネントを変更すると、カーネルの組み合わせが無効になったり、推測受理率が低下したりする可能性があります。

  • 重み: Mia-AiLab/GLM-5.3-Flash-EXL3-TR3-4bpw。ミラーが利用できない、または不完全な場合は Brandon Music リポジトリにフォールバックします。
  • 並列処理: 2 ノード、テンソル並列サイズ 2、マルチプロセスエグゼキューターを使用します。
  • 量子化: exl3。ルーティングされたエキスパートはパックされ、dense、共有エキスパート、attention、embedding、出力ヘッドの重みはネイティブ形式です。
  • ターゲット KV キャッシュ: fp8。内部ではパックされた fp8_ds_mla として表現されます。
  • 推測実行: DFlash2。推測トークン数は 7、ドラフトのテンソル並列処理は 1 です。
  • ドラフト KV キャッシュ: 自動選択。ターゲットの MLA レイアウトではなく、dense ドラフトモデルには BF16 が使用されます。
  • Attention: ターゲットには sparse MLA、DFlash2 のドラフト attention には自動選択された FLASH_ATTN を使用します。
  • コンテキスト: MAX_MODEL_LEN=900000。
  • 同時実行数: MAX_NUM_SEQS=4。
  • Prefill: MAX_NUM_BATCHED_TOKENS=1024。
  • メモリ使用率: GPU_MEM_UTIL=0.87。

推測デコードモードを切り替える

DFlash2 がデフォルトで、incoai/GLM-5.3-Flash-DFlash2 を使用します。推測トークン数 2 のチェックポイントの MTP パスにフォールバックするには、次のコマンドで再起動します。

SPEC_METHOD=mtp ./start.sh restart

環境変数では SPEC_METHOD=none もサポートされています。DFlash2 のデフォルトのドラフトテンソル並列処理は 1 です。これにより、小さなドラフトモデルを rank 0 に保持し、ドラフトの各ステップで CX7 通信が発生するのを避けられます。

DFlash2 で TRITON_ATTN を強制しないでください。README の測定結果によると、このバックエンドではドラフトブロック内の attention が因果的になり、後続の推測位置での受理率が急落しました。ドラフト attention は未設定のままにし、SM121 が FLASH_ATTN を選択するようにしてください。

KV キャッシュと長文脈設定

ターゲット KV キャッシュは fp8 のままにする必要があります。このアーキテクチャでは、sparse-MLA カーネルがパックされた fp8_ds_mla を受け付けます。BF16 には互換性のある sparse カーネルがなく、NVFP4 KV カーネルは sparse MLA ではなく dense MHA に適用されます。

DFlash2、vision サポート、0.87 のメモリ使用率、900,000 の最大モデル長を使用した場合、README では 982,612 トークンのプールが確保され、fp8 MLA に約 15.67 GiB が使用されると報告されています。これは、900,000 トークンの完全なリクエスト 1 件分の約 1.09 倍の容量です。文書化された設定では、ネイティブな 1,000,000 トークン構成は依然として割り当てられません。

意図的にランタイムを変更してテストする場合を除き、次の設定を維持してください。

KV_CACHE_DTYPE=fp8
GPU_MEM_UTIL=0.87
MAX_MODEL_LEN=900000
MAX_NUM_BATCHED_TOKENS=1024
SKIP_MM_PROFILING=1
LIMIT_MM={"image":4,"video":1}

SKIP_MM_PROFILING=1 は重要です。最大サイズの画像と動画のダミー入力をプロファイリングすると、統合メモリを使い果たす可能性があるためです。README では、バッチトークン上限を 8,192 に引き上げると、長文脈動作中に GB10 の indexer top-k パスが過剰サブスクライブされることにも注意を促しています。

プレフィックスキャッシュの動作

プレフィックスキャッシュは有効ですが、OpenAI APIはステートレスのままです。クライアントは各ターンで会話履歴全体を再送する必要があります。vLLMは送信されたプレフィックスをハッシュ化し、キャッシュされたブロックがまだ利用可能であれば再利用することがあります。

  • 文書化されているMLAキャッシュマネージャーでは、ブロック境界に揃ったトークンだけがヒットとしてカウントされます。
  • MAX_NUM_SEQS=4は同時に処理できる生成を4つにしますが、永続的なチャットセッションを4つ予約するものではありません。
  • アイドル状態の会話がキャッシュに残り続ける保証はありません。
  • ある会話のアクティベーションが別の会話と混在することはありません。
  • 別のワークロードによってプレフィックスが追い出された場合、古いチャットでは新たなプリフィルが必要になることがあります。

READMEのライブテストでは、7,760トークンのフォローアップのうち3,584トークン、約46パーセントのプロンプトが再利用されました。プレフィックスキャッシュは永続的なセッションストレージではなく、状況に応じた高速化として扱ってください。

デコード性能の測定

リポジトリには、ストリーミングデコードと整合性チェック用のtests/bench_decode.pyが含まれています。構造化カウントテストは次のように実行します。

python3 tests/bench_decode.py \
  --phase structured \
  --structured \
  --runs 5 \
  --max-tokens 400 \
  --skip-coherence \
  --out /tmp/glm53-structured.json

ハッシュマップの説明を散文で生成するテストは次のように実行します。

python3 tests/bench_decode.py \
  --phase prose \
  --runs 5 \
  --max-tokens 400 \
  --skip-coherence \
  --out /tmp/glm53-prose.json

READMEに記載された、ウォーム状態かつ空のKVで行うプロトコルでは、構造化ワークロードは同時実行数1で毎秒62.9トークン、同時実行数2で合計毎秒103.3トークン、同時実行数4で合計毎秒146.5トークンに達しました。性能は投機的受理に大きく左右されます。ラボの中央値は構造化出力で毎秒61.7トークンでしたが、散文では毎秒26.9トークンでした。約60,000~100,000のキャッシュ済みトークンを使う混合テストや長いコンテキストのテストでは、毎秒24~27トークンと報告されています。

これらの数値は、READMEに記載された2台のGB10構成、プロンプトの種類、温度0の設定、思考機能の無効化、DFlash2のk=7、および400トークン生成という条件に固有のものです。普遍的なスループット保証として解釈しないでください。

任意の拒否方向アブレーション

リポジトリでは、EXL3チェックポイントを書き換えたり再量子化したりせずに、重みのロード時に拒否方向アブレーションを適用できます。次のように有効化します。

ABLIT=1 ./start.sh restart
./start.sh logs | grep ablit

デフォルトのレシピでは、レイヤー15~45にある各ネイティブBF16のself_attn.o_projを編集します。レイヤー0~14は安全性のアンカーとして変更されません。デフォルトのスケールはABLIT_ALPHA=3.0です。1.0に設定すると、指定された方向に沿う成分を除去する単純な射影が適用されます。

利用できる主な設定は次のとおりです。

  • ABLIT=0または未設定で、標準の重みを変更しません。
  • ABLIT_DIRECTION=dealignで、公開されているデフォルト方向を使用します。
  • ABLIT_LAYERS=15-45で、編集対象の範囲を両端を含めて指定します。
  • ABLIT_ALPHA=3.0で、射影のスケールを指定します。
  • ABLIT_INCLUDE_MTP=1で、MTPを使用する場合にチェックポイントのMTPブロックを含めます。

READMEのKLD品質結果は、アブレーションなしで測定されています。これを有効にすると拒否動作が変わり、整合性や投機的受理に影響する可能性があります。DFlash2のドラフターは変更されない一方で、ターゲットの出力が変化するためです。整合性が低下した場合、READMEではまずABLIT_ALPHAを下げることを推奨しています。

高度な起動ワークフロー

両方のマシンにイメージとモデルキャッシュが存在する場合、繰り返しの転送処理を省略できます。

SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh

ローカルのコンテナイメージを保持し、pull、ダウンロード、同期をすべて省略するには、次を実行します。

SKIP_PULL=1 SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh restart

公開イメージではなく、現在のリポジトリからオーバーレイを再ビルドするには、次を実行します。

BUILD=1 SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh restart

Dockerfileを直接ビルドすることもできます。

docker build -t glm53-flash-sm121:local .

起動スクリプトは通常、イメージをワーカーに送る前にGPUオーバーレイのセルフチェックを実行します。SKIP_OVERLAY_VERIFY=1は、そのチェックを意図的に回避する場合にのみ設定してください。

重要な設定に関する警告

  • --moe-backend marlinを渡さないでください。このデプロイメントではEXL3の重みと独自のパック済みエキスパート方式を使用します。
  • ターゲットKVキャッシュをNVFP4またはBF16に設定しないでください。KV_CACHE_DTYPE=fp8を維持してください。
  • 投機的ドラフトのアテンションをTRITON_ATTNに固定しないでください。
  • イメージを古いglm53-flash-sm121:v8のNVFP4/Rayデプロイメントに置き換えないでください。
  • テンソル並列度、ノード数、CX7ピン、USE_HOST_NCCLを不用意に変更しないでください。これらは2ノード構成に不可欠です。
  • 完全なモデルを再度ダウンロードするつもりでない限り、Hugging Faceチェックポイントキャッシュを削除または再量子化しないでください。
  • 統合メモリの使用量を考慮せずに、マルチモーダルプロファイリングの保護機能を無効にしないでください。
  • 隠れサイズを検証せずに、ABLIT_DIRECTIONを無関係なチェックポイントのベクトルに指定しないでください。

トラブルシューティング

サービスが正常な状態にならない

./start.sh logsと./start.sh logs workerで両方のログを確認してください。パスワードなしのSSH、空きディスク容量、Dockerの権限、キャッシュの完全性、CX7インターフェース名を確認します。初期の重みのロードとグラフキャプチャには時間がかかるため、ログで進行状況を確認してから、デフォルトの準備完了タイムアウトが終了するまで待ってください。

ランク初期化中にNCCLがハングする

HEAD_CX7_IF、WORKER_CX7_IF、HEAD_CX7_IB、WORKER_CX7_IBを確認してください。文書化されているデフォルト値はラボの物理ポートに対応しているため、配線が異なる場合は調整が必要になることがあります。

ワーカーがGHCRにアクセスできない

ワーカーがGHCRへ直接アクセスする必要はありません。ヘッドがパブリックイメージを取得し、SSH経由で転送します。ヘッドで匿名アクセスのレート制限に達した場合は、GHCR_USERとGHCR_TOKENを設定してください。

投機的デコーディングが予想外に遅い

SPEC_METHOD=dflash、DFLASH_TOKENS=7が設定され、ドラフトアテンションがTRITON_ATTNに強制されていないことを確認してください。また、投機的デコーディングの性能は出力形式によって変わる点にも注意してください。高度に構造化されたシーケンスは、制約のない文章より受理率が大幅に高くなる場合があります。

まとめ

このプロジェクトは、コンパクトなEXL3重み、fp8 sparse-MLAキャッシュ、DFlash2投機的デコーディングを使用して、2台のNVIDIA GB10システムを2ランクのOpenAI互換GLM-5.3 Flashサーバーに変えます。最も速い手順は、用意されているネットワーク、KV、アテンション、量子化のデフォルト値を維持し、./start.shで起動したうえで、ヘルスエンドポイント、チャットAPI、ログ、付属のデコードベンチマークを通じてデプロイを検証することです。