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

ホストRAMオフロードで24GB RTX 3090 1枚上にGLM-5.3-Flashを実行する

このチュートリアルでは、glm53-flash-offloadがページ固定ホストメモリ、伸縮可能なGPUエキスパートキャッシュ、ゼロコピーPCIeアクセス、オプションのAVX2 CPU計算を組み合わせ、24GBのNVIDIA GPU 1枚でGLM-5.3-Flashを提供する方法を説明します。Dockerイメージのインストール、fastモードまたはexactモードの選択、APIの呼び出し、パフォーマンスの検証、デプロイの調整までを行います。

ホストRAMオフロードで24GB RTX 3090 1枚上にGLM-5.3-Flashを実行する

概要

glm53-flash-offload は、単一の24 GB NVIDIA GPUとホストDDR4メモリ上で、GLM-5.3-Flashの125.3 GB、EXL3 3.05-bpwビルドを提供します。OpenAI互換のHTTP APIを公開しながら、モデルのルーティングされたmixture-of-experts重みを主にピン留めしたシステムRAMに保持します。

このプロジェクトは、標準のexllamav3 1.5.1に対する薄いmonkey patch群と、いくつかの小規模なカスタムカーネルで構成されています。exllamav3のソースコードを編集する必要はありません。文書化された構成は、PCIe 4.0 x16でAMD EPYC 7443Pシステムに接続したRTX 3090で測定されています。

中心となる考え方は、頻繁に使用されるエキスパートを可変サイズのGPUキャッシュに保持することです。キャッシュから外れたエキスパートは、PCIe経由でピン留めしたホストメモリから直接読み取れます。高速モードでは、デコード時に最も低温なキャッシュミスをAVX2 CPUワーカーで処理することもできます。

主な機能

  • 単一GPUでのデプロイ: 24 GBのRTX 3090クラスGPU 1基でGLM-5.3-Flashを提供します。
  • OpenAI互換API: チャット補完、テキスト補完、モデル検出、ストリーミング、推論コンテンツ、OpenAI形式のツール呼び出しに対応します。
  • ピン留めゼロコピーストレージ: ルーティングされたすべてのエキスパートをピン留めしたホストRAMに保持し、CUDA unified virtual addressing経由でアクセスできます。
  • 可変GPUエキスパートキャッシュ: 使用頻度の高いエキスパートを空きVRAMに配置し、長いプリフィルのアクティベーションやステージングバッファ用に、キャッシュ領域を一時的に戻すこともできます。
  • プリフィルステージング: 非キャッシュのエキスパートを1層先にコピーし、PCIe転送と計算をオーバーラップさせます。
  • オプションのCPU層: 高速モードでは、選択されたデコード時の低温キャッシュミスをAVX2 CPUカーネルに割り当てます。
  • バッチデコード: 文書化された-ambs 4構成では、最大4ストリームを同時にデコードできます。
  • 再現可能な構成: モデルリビジョン、コンテナダイジェスト、exllamav3のバージョン、Tritonの選択、ベンチマーク、品質確認用の参照パネルを固定しています。

高速モードと正確モードの選択

サーバーはGLM53_MODE環境変数で2つの動作モードを提供します。

高速モード

fastがデフォルトです。GPUエキスパートキャッシュ、ゼロコピーのキャッシュミス処理、選択されたデコード時の低温キャッシュミスに対するAVX2 CPU処理、バッチデコード、融合デコードカーネルを組み合わせます。測定したホストでは、約218 GiB、つまり234 GBのホストRAMを使用しました。

公開された測定では、デコードストリーム1本で約28.15トークン/秒、2ストリームで合計31.57トークン/秒、4ストリームで合計33.98トークン/秒でした。現在のダイジェストを使用した画像スモークテストでは、それぞれ合計28.88、31.27、35.00トークン/秒でした。

品質に関する警告: プリフィルは正確ですが、高速モードのデコードは標準のexllamav3に対してビット単位で完全一致するわけではありません。ペア比較によるデコードチェックでは、平均KL 0.0053、top-1一致率0.977が報告されています。出力の同等性が必要な場合は、正確モードを使用してください。

正確モード

exactはCPU層と高速モード専用のデコードカーネルを無効にします。GPUエキスパートキャッシュと、ホストメモリのキャッシュミスに対するゼロコピー処理は維持します。参照パネルではtop-1一致率1.0000、KL 0が測定され、ホストメモリ使用量は約111 GiB、つまり119 GBでした。

正確モードは低速ですが、RAM使用量は大幅に少なくなります。測定された単一ストリームのデコード速度は、短いテストコンテキストで毎秒12.57トークンでした。一方、標準のexllamav3が収まらないエキスパートをCPUワーカーに配置した場合は、毎秒約7.5~8.4トークンでした。

ハードウェアとソフトウェアの要件

GPUとドライバー

  • VRAM 24 GBのNVIDIA GPU 1基。
  • 測定対象は、RTX 3090やA5000などのsm_86 GPUです。
  • 付属のsm_86バイナリはRTX 4090を含むsm_89でも動作しますが、その構成は測定していません。
  • イメージがCUDA 13.0.3を使用するため、CUDA 13.0対応のNVIDIAドライバーが必要です。
  • PCIe 4.0 x16を推奨します。測定したリンクでは、キャッシュミスに約25 GB/秒を消費します。

ホストメモリ

  • 高速モード: 他の処理をほとんど実行しない場合でも、合計256 GiBが最低限必要です。320 GB以上を推奨します。Dockerのメモリ制限を使用する場合は、少なくとも230gを割り当ててください。
  • 正確モード: 128 GiBが最低限必要で、160 GB以上を推奨します。

CPUとストレージ

  • 高速モードにはAVX2、FMA、F16C対応のx86-64 CPUが必要です。
  • 測定された高速モードの動作には、物理コア約24個と、8チャネルDDR4以上を推奨します。
  • チェックポイントはディスク上で約117 GiB、つまり125.3 GBを占有します。
  • モデルの読み込み時間を短縮するため、NVMeストレージを推奨します。
  • 文書化されたセットアップには、Docker、NVIDIA Container Toolkit、Hugging Face CLIが必要です。

Dockerでサーバーをインストールして起動する

ステップ1: チェックポイントをダウンロードする

固定された3.05-bpwチェックポイントをローカルディレクトリにダウンロードします。

hf download turboderp/GLM-5.3-Flash-exl3 \
  --revision 3.05bpw \
  --local-dir /data/GLM-5.3-Flash-exl3-3.05bpw

代わりに、空のディレクトリを/modelsにマウントすることもできます。config.jsonがない場合、コンテナは設定されたチェックポイントをそのディレクトリにダウンロードします。

ステップ2: 高速モードを起動する

次のコマンドはGPU 0でサーバーを起動し、ポート30000で公開します。ストリーミング配信の修正を含むイメージダイジェストを使用します。

docker run -d \
  --name glm53 \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d

--ulimit memlock=-1 の設定を推奨します。サーバーは大量のホストメモリをピン留めするためです。公開イメージは、測定に使用したドライバーではこの設定なしでも読み込みに成功しましたが、すべてのホストで同じ動作になるとは限りません。

ステップ 3: 起動を監視する

docker logs -f glm53

loaded in ... s を含むメッセージが表示されるまで待ちます。記載されているシステムでは、キャッシュやホストの状態によって異なりますが、起動にはおよそ2~3分かかります。

ステップ 4: ヘルス状態を確認する

curl -s http://localhost:30000/health

exact モードを実行する

出力の同等性を優先し、ホストメモリの使用量を抑えるには、-e GLM53_MODE=exact を追加します。

docker run -d \
  --name glm53-exact \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -e GLM53_MODE=exact \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d

fast と exact の例を同じポートで同時に実行しないでください。モードを切り替える前に、最初のコンテナを停止して削除します。

docker rm -f glm53

基本的な API の使用方法

チャット補完を送信する

curl -s http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Explain zero-copy model offloading."}],"max_tokens":512}'

デフォルトで提供されるモデル名は glm-5.3-flash です。明示的に設定しない限り、max_tokens は小さな固定値ではなく、残りのコンテキスト長をデフォルト値として使用します。

思考を無効にする

GLM の推論は reasoning_content に返されます。リクエストで思考を無効にするには、チャットテンプレートのオプションを渡します。

curl -s http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Reply with one sentence."}],"chat_template_kwargs":{"enable_thinking":false},"max_tokens":128}'

レスポンスをストリーミングする

curl -N http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Write a short explanation of mixture-of-experts models."}],"stream":true,"max_tokens":512}'

上記に示した固定の bb633b0b... ダイジェストを使用してください。以前の 1159044a... イメージはフル速度で生成できましたが、最後に滞留分をまとめてフラッシュするまで、ストリーミングイベントの配信速度はおよそ半分でした。

利用可能なモデルを一覧表示する

curl -s http://localhost:30000/v1/models

ランタイム統計を確認する

curl -s http://localhost:30000/stats

統計エンドポイントには、エキスパートキャッシュのヒット情報と CPU 層のカウンターが含まれます。その他のエンドポイントには、/v1/completions、/server_info、SGLang 形式の /generate および /tokenize ルートがあります。

このデプロイメントはテキスト専用です。チェックポイントのビジョンタワーは読み込まれません。

OpenAI 形式のツールを使用する

チャットエンドポイントは tools フィールドを受け付けます。GLM 内部の <tool_call> 形式で生成されたツール式は、レスポンス内で OpenAI 互換の tool_calls に変換されます。そのため、クライアントアプリケーションでは通常のツール呼び出しループを使用できます。ツール定義を送信し、アシスタントのツール呼び出しを確認して関数を実行し、別のメッセージとしてツール結果を送り返します。

コンテキストとサーバー引数を調整する

イメージ名の後に置いた引数はサーバーコマンドに追加され、最後の値が有効になります。たとえば、65,536 トークンの KV キャッシュを使用するには、次のようにします。

docker run -d \
  --name glm53-64k \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d \
  -cs 65536

KV キャッシュを小さくすると、より多くのエキスパートキャッシュ用スロットを確保できる場合があります。公開ベンチマーク構成では、131,072 トークンの KV キャッシュ、最大バッチサイズ 8、チャンクサイズ 8,192 を使用しました。

Docker を使わずにインストールする

ネイティブインストールには、対象 GPU 向けにビルドされた exllamav3 1.5.1 が必要です。プロジェクトをクローンしたディレクトリで拡張機能のインストーラーを実行し、リポジトリとモデルのパスを設定して、付属のエントリポイントを起動します。

scripts/install.sh
GLM53_ROOT=$PWD \
GLM53_MODEL_DIR=/path/to/model \
docker/entrypoint.sh

インストーラーはプロジェクト独自の拡張機能をビルドします。CUDA、PyTorch、Triton、SGLang、exllamav3、プロジェクトのコミット、テスト済みのサーバー構成を固定できるため、最も再現性の高い方法は引き続き Docker です。

品質とパフォーマンスを検証する

リファレンスパネルを採点する

リポジトリのクローンから、標準ライブラリのみを使用する付属のベンチマーククライアントを実行します。

python3 bench/score_ref_panel.py \
  --url http://127.0.0.1:30000 \
  --panel reference/glm-5.3-flash-exl3-ref-panel.json \
  --out score.json

教師強制パネルでは、fast モードと exact モードの両方で、top-1 一致率 1.0000、KL 0 が報告されるはずです。このパネルは prefill または教師強制経路を評価するものであり、fast モードの自己回帰デコードが exact であることを示すものではありません。

速度スイープを実行する

python3 bench/sweep.py \
  --url http://127.0.0.1:30000 \
  --card rtx-3090-24gb/glm-5.3-flash-offload \
  --template glm \
  --config "bb633b0b fast" \
  --prefill 8192 32768 \
  --conc 1 2 4 \
  --reps 3 \
  --dec-reps 2 \
  --no-early-exit \
  --out sweep.json

ストリーミング配信を確認する

python3 bench/stream_rate.py --url http://127.0.0.1:30000

成功時は、レスポンスのおよそ半分が最後にまとめて表示されるのではなく、テキストが均等に届くことを確認できます。

高度なチューニング

CPU層のサイズを決める

デフォルトでは、GLM53_CT_CPUS=auto は物理コアごとに1つの論理CPUを選択し、オペレーティングシステムとGPUを駆動するPythonスレッドのために、先頭の2つの物理コアを空けておきます。測定した24コアのホストでは、CPU 2から23までと22個のワーカースレッドが使用されました。

明示的に割り当てる場合は、次のような値を設定します。

-e GLM53_CT_CPUS=2-23 \
-e GLM53_CT_THREADS=22

CPUのコストモデルでは、22スレッドで1エキスパートあたり0.104ミリ秒として測定された GLM53_CT_B を使用します。N 個のワーカースレッドの場合、READMEでは 0.104 x 22 / N として見積もることを推奨しています。たとえば、2コアを空けた16コアのホストでは、14個のワーカースレッドと約0.16の値を使用します。

物理コアが約12個未満の場合、ほとんどのミスはPCIe経路に戻ると予想され、性能はexactモードに近づきます。その場合は、exactモードの方が適している可能性があります。

CPU層のメモリ配置を制御する

GLM53_CT_SWZ=1 により、CPU層はエキスパートのブロック連続型の別コピーを使用します。これは測定済みの高速構成で、RAM使用量が約114.2 GB増加します。0 に設定すると、CPU層は固定されたホームコピーを直接読み取るため、メモリ使用量は大幅に減少しますが、プロジェクトの報告ではCPUエキスパートカーネルのベンチマークが約40%遅くなります。この設定でのエンドツーエンド性能は測定されていません。

キャッシュ予約を調整する

GLM53_EC_RESERVE_GB は、エキスパートキャッシュの割り当て後にVRAMを空けておきます。デフォルトはfastモードで1.5 GB、exactモードで1.0 GBです。長いプリフィルでメモリ不足になる場合を除き、fastモードの予約は1.5 GBのままにしてください。

GLM53_EC_ELASTIC_GB のデフォルトは10 GBです。この量のキャッシュメモリは、プリフィルのアクティベーションとステージングのために解放され、その後デコード用に再取得できます。GLM53_EC_STAGE_GB はステージングバッファ1つあたりデフォルト2.6 GBで、オーバーラップのために2つのバッファが使用されます。

より大容量のGPUを使用する

エキスパートキャッシュは、モデルの読み込みと設定された予約の後に利用可能なVRAMからサイズを決定します。そのため、32 GBまたは48 GBのカードではより多くのエキスパートスロットが割り当てられ、ヒット率が向上し、デコード性能が改善されるはずです。これらの大容量カードでの結果はREADMEに記載されていません。

RTX 4090では同梱の sm_86 ビルドを実行できますが、測定は行われていません。Blackwellでは、次の指定で再ビルドが必要です。

TORCH_CUDA_ARCH_LIST="8.6;12.0"

別のアーキテクチャでは、新しいTritonのピン留めも必要になる場合があります。作成する場合は、基準パネルがtop-1 1.0000およびKL 0のままであることを確認してください。

Tritonの正確な選択を保護する

イメージは data/triton_pin_exact.json を通じて、KDA線形アテンションのプリフィルカーネル選択を固定します。Tritonに別の構成を選択させると、浮動小数点の丸めが変わる可能性があります。基準と同等のプリフィル動作が重要な場合は、GLM53_TRITON_PIN をデフォルトのままにしてください。

オフロードパイプラインの仕組み

  1. ルーティングされたエキスパートを固定ホストメモリに読み込む。 各レイヤーには正確なサイズの固定アリーナが割り当てられ、exllamav3のエキスパートポインターはCUDA UVAエイリアスを参照します。
  2. VRAMに弾性CLOCKキャッシュを構築する。 ルーターの選択を重複排除し、キャッシュヒットを記録して、受け入れたミスのために追い出す対象を選択します。
  3. キャッシュされていないエキスパートをPCIe経由で読み取る。 exllamav3のカーネルは、ホスト側で同期コピーを行わずに、固定ホスト表現へアクセスできます。
  4. 長いプリフィルをステージングする。 レイヤーごとの選択数が十分に大きい場合、欠落したエキスパートを1つ前のレイヤーの計算中に、1レイヤー先のステージングバッファへコピーします。
  5. fastモードで選択されたデコードミスを分割する。 コストモデルにより、よりウォームなミスはゼロコピーGPU実行へ送り、選択されたコールドミスはCPU層へ送ります。
  6. CPUとGPUの結果を結合する。 CPUは固定マップメモリを通じて処理結果を公開し、GPUはホスト同期ではなくデバイス側フラグを待機した後、得られたFP32部分結果を加算します。

運用上の注意

  • デコード出力を標準のexllamav3と一致させる必要がある場合は、GLM53_MODE=exact を使用してください。
  • ストリーミングのレイテンシーが重要な場合は、古い sha256:1159044a... イメージを避けてください。記載されている sha256:bb633b0b... ダイジェストを使用します。
  • fastモードでは現在、ホストRAMに2つのエキスパートコピーが保持されます。コンテナを起動する前に十分なメモリを確保してください。
  • 低速なPCIeリンクで、測定されたRTX 3090のスループットが得られるとは限りません。デコード速度はキャッシュミスのトラフィックに左右されます。
  • コンテキストサイズ、キャッシュ予約、同時実行数、またはステージング設定を変更する場合は、/stats、システムメモリ、GPUメモリを監視してください。
  • サーバーはテキストのみを処理し、このデプロイでは画像入力はサポートされません。

結論

glm53-flash-offloadは、固定ホストストレージ、ゼロコピーPCIe読み取り、弾性VRAMキャッシュ、ステージングされたプリフィル転送、オプションのAVX2 CPU層を組み合わせることで、非常に大規模なmixture-of-expertsチェックポイントを単一の24 GB GPUで実用的にします。まず固定済みのDockerイメージから始め、出力の忠実性にはexactモード、スループットにはfastモードを選択します。その後、キャッシュやCPU設定を調整する前に、付属の品質、速度、ストリーミング確認でインストールを検証してください。