NVIDIA srt-slurm で LLM ベンチマークを検証
NVIDIA は、srt-slurm フレームワークと srtctl ツールを用いて、宣言型 YAML 設定から再現可能な分散 LLM サービングベンチマークワークフローを構築・検証する実践的なチュートリアルを提供した。
キーポイント
srt-slurm フレームワークの紹介と srtctl の活用
宣言型 YAML 設定ファイルを、再現可能な SLURM ベンチマークワークフローに変換する NVIDIA の srt-slrum フレームワークと、その CLI ツールである srtctl の使用方法を解説している。
Google Colab を活用した開発環境の構築
実際の GPU クラスターがない Google Colab 環境でプロジェクトを設定し、内部アーキテクチャの検証やレシピのドライランを通じて、本番環境への移行準備を安全に行う手法を示している。
パラメータスイープとパレート分析による最適化
スループット対レイテンシのパレートフロンティアを用いてベンチマーク結果を分析し、DeepSeek-R1 のようなモデルに対する非集約型(disaggregated)プリフェッチ・デコード配置のモデル化やパラメータスイープの実行方法を提示している。
多様なバックエンドとレシピのサポート
sglang、trtllm、vllm などのエンジンアダプターをサポートし、GB200、H100、B200 などのプラットフォームや Qwen3-32b などのモデルに対応した事前準備されたベンチマークレシピを提供している。
モジュール化されたリポジトリ構造
srtctl は CLI、コアロジック(スキーマ/スラーム生成)、エンジンアダプター(SGLang, vLLM など)、および分析コンポーネントを分離した明確なディレクトリ構成を採用しています。
シミュレーション可能な設定ファイル
srtslurm.yaml により、実際の SLURM クラスターへのアクセスがなくても、GPU 数やコンテナパスなどのデフォルト値を定義し、レシピベースのベンチマーク実行をローカルで検証できます。
多様なバックエンドと分析機能
SRT ベンチマークは複数の推論エンジン(SGLang, TRTLLM, vLLM)に対応し、生成されたログ解析やパレート最適化を可視化する Streamlit ダッシュボードを提供します。
重要な引用
convert declarative YAML configurations into reproducible SLURM benchmark workflows for distributed LLM serving
generate parameter sweeps, interact with the typed Python API, validate expanded configurations, and analyze simulated benchmark results through a throughput-versus-latency Pareto frontier
use it as a practical development workspace to understand, validate, and prepare production-grade benchmark recipes before we submit them to an actual GPU cluster
src/srtctl/ ... backends/ sglang.py, trtllm.py, vllm.py, mocker.py ← engine adapters
analysis/ srtlog (log parsers) + Streamlit dashboard (Pareto, latency...)
"We dry-run the built-in mocker recipe to examine how srtctl validates configurations and generates SLURM submission artifacts without executing a real benchmark."
影響分析・編集コメントを表示
影響分析
この記事は、大規模言語モデルの分散サービング環境を構築・最適化する際、標準化されたベンチマーク手法と自動化ツールを提供することで、開発者の生産性と信頼性を大幅に向上させる。特に、本番環境への移行前のシミュレーションと検証プロセスを明確に定義している点は、実運用におけるリスク低減とパフォーマンス最大化に直結する重要な貢献である。
編集コメント
本チュートリアルは、複雑な分散 LLM 環境のベンチマークを「宣言型設定」という現代的なアプローチで扱い、再現性と検証可能性を担保する点で非常に価値が高いです。特に、実際のクラスターへの投入前に Colab でシミュレーションを行う手法は、リソースコストを抑えつつ最適な構成を見つけるための現実的な解決策と言えます。
本チュートリアルでは、NVIDIA の srt-slurm フレームワークを取り上げ、宣言的な YAML 設定を再現可能な SLURM ベンチマークワークフローに変換する srtctl ツールの活用方法を解説します。Google Colab でプロジェクトを設定し、内部アーキテクチャを検証した上でクラスター構成を定義。組み込みおよびカスタムのレシピを実行前の確認(dry-run)で試し、DeepSeek-R1 向けの非同期プリフェッチ・デコード展開モデルも構築します。
さらにパラメータスイープの生成、型付き Python API の操作、拡張された設定の検証を行い、スループットとレイテンシのパレートフロンティアを通じてシミュレーション結果を分析します。Colab には実際の SLURM 環境は用意されていませんが、GPU クラスターへの提出前にベンチマークレシピを理解・検証・準備するための実用的な開発ワークスペースとして活用しています。
Copy CodeCopiedUse a different Browser
import os, sys, subprocess, textwrap, json, shutil, importlib
from pathlib import Path
def run(cmd, check=True, quiet=False):
"""Run a shell command, stream output."""
print(f"\n$ {cmd}")
r = subprocess.run(cmd, shell=True, text=True, capture_output=True)
out = (r.stdout or "") + (r.stderr or "")
if not quiet:
print(out[-6000:])
if check and r.returncode != 0:
raise RuntimeError(f"Command failed ({r.returncode}): {cmd}")
return out
def section(title):
print("\n" + "═"*78 + f"\n {title}\n" + "═"*78)
section("1. Install srt-slurm")
REPO = Path("/content/srt-slurm") if Path("/content").exists() else Path.cwd()/"srt-slurm"
if not REPO.exists():
run(f"git clone --depth 1 https://github.com/NVIDIA/srt-slurm.git {REPO}", quiet=True)
run(f"{sys.executable} -m pip install -q -e {REPO}", quiet=True)
sys.path.insert(0, str(REPO / "src"))
importlib.invalidate_caches()
os.chdir(REPO)
run("srtctl --help")
Colab 環境の準備として、必要なモジュールを読み込み、コマンド実行や見出しフォーマットに再利用できるヘルパー関数を定義します。次に NVIDIA の srt-slurm リポジトリをクローンし、編集可能なモードでインストールして Python ランタイムからソースディレクトリが参照できるように設定します。最後にリポジトリのディレクトリへ移動し、srtctl コマンドラインインターフェースが正しくインストールされたか確認します。
Copy CodeCopiedUse a different Browser
- リポジトリのアーキテクチャ
このプロジェクトのディレクトリ構成は以下の通りです。
src/srtctl/ には、CLI ツールが格納されています。cli フォルダ内では submit.py がジョブの送信(適用・ドライラン・事前チェック・監視)やパラメータスイープの実行、インタラクティブモードを担当しています。core フォルダには、型付き設定を扱う schema.py、スイープ処理の sweep.py、スラーム用 sbatch スクリプト生成の slurm.py、および検証、ヘルスチェック、トポロジー解析、フィンガープリント作成を担当するモジュールが配置されています。また、backends フォルダには SGLang、TensorRT-LLM、vLLM などの推論エンジンに対応するアダプター(mocker.py を含む)が実装され、frontends には Dynamo やルーター用のフロントエンドが用意されています。テンプレートは Jinja2 で記述され、sbatch スクリプトやオーケストレーター用スクリプトとして生成されます。
recipes フォルダには、プラットフォームごとの事前準備済みベンチマーク(GB200-FP4、H100、B200-FP8、Qwen3-32b、DSv4-Pro、モッカーのスマークテストなど)が格納されています。analysis フォルダでは SRT ログを解析するパーサーと、パレート分析やレイテンシ可視化を行う Streamlit ダッシュボードが提供されます。docs フォルダにはスイープ手順、プロファイリング方法、データ分析ガイド、設定リファレンスなどのドキュメントが用意されています。
- クラスター設定(srtslurm.yaml)
クラスター設定ファイル srtslurm.yaml では、以下のパラメータを定義します。クラスター名は "colab-demo"、デフォルトのアカウントは "demo-account"、パーティションは "gpu" を使用します。ジョブの最大実行時間は 1 時間(01:00:00)に設定され、ノードあたりの GPU 数は 4 個です。また、use_gpus_per_node_directive と use_segment_sbatch_directive はそれぞれ true に設定されており、コンテナイメージとして Dynamo-SGLang 用と LMSYS Org の SGLang v0.5.5.post2 用の SQSH ファイルが指定されています。モデルパスには DeepSeek-R1 の格納先も定義されています。
srtctl がコマンドラインツール、スキーマ、バックエンド、テンプレート、レシピ、分析コンポーネントをどのように整理しているかを確認するため、リポジトリの構造を検証します。その後、シミュレートされたクラスターデフォルト、コンテナエイリアス、GPU 設定、モデルパスを含むローカルの srtslurm.yaml ファイルを作成します。
この構成ファイルを使用することで、実際の SLURM クラスターへのアクセスがなくても、Colab 上でレシピ参照を解決することが可能になります。
- ドライラン:モックサーキットテストと生成された sbatch スクリプト
recipes/mocker/agg.yaml を指定して srtctl dry-run を実行し、エラーなくスクリプトが生成されるか確認します。
- カスタム非集約レシピ(プリフィル/デコード分割)
以下に、プリフィルとデコード処理を別ノードで処理するカスタム設定ファイルの例を示します。この設定では、DeepSeek-R1 モデルを fp8 精度で動作させ、GB200 GPU を使用してリソースを最適化しています。
name: "colab-disagg-demo"
model:
path: "deepseek-r1"
container: "lmsysorg+sglang+v0.5.5.post2.sqsh"
precision: "fp8"
resources:
gpu_type: "gb200"
gpus_per_node: 4
prefill_nodes: 1
decode_nodes: 2
prefill_workers: 1
decode_workers: 2
backend:
prefill_environment: { PYTHONUNBUFFERED: "1" }
decode_environment: { PYTHONUNBUFFERED: "1" }
sglang_config:
prefill:
served-model-name: "deepseek-ai/DeepSeek-R1"
model-path: "/model/"
trust-remote-code: true
kv-cache-dtype: "fp8_e4m3"
tensor-parallel-size: 4
disaggregation-mode: "prefill"
decode:
served-model-name: "deepseek-ai/DeepSeek-R1"
model-path: "/model/"
trust-remote-code: true
kv-cache-dtype: "fp8_e4m3"
tensor-parallel-size: 4
disaggregation-mode: "decode"
benchmark:
type: "sa-bench"
isl: 1024
osl: 1024
concurrencies: [64, 128, 256]
req_rate: "inf"この my-disagg.yaml を指定して再度 srtctl dry-run を実行し、設定が正しく適用されるか検証します。
まず、組み込みのモックレシピをドライラン実行し、srtctl が実際のベンチマークを実行せずに設定を検証し、SLURM 提出用アーティファクトをどのように生成するかを確認します。次に、プリフェッチとデコードのワークロードを独立したノードおよびワーカープールに分離する、高度な DeepSeek-R1 レシピを定義します。この分散型 SGLang 構成も別のドライランで検証し、サービングパラメータがジョブスクリプトにどのように変換されるかを精査します。
Copy CodeCopiedUse a different Browser
- パラメータスイープ(グリッドサーチ)の実行前テストとディスクへの展開
まず、srtctl dry-run コマンドを実行して、指定した設定ファイル(例:examples/example-sweep.yaml)が正しく解釈されるか確認します。この際、エラーが発生しても処理を続行するよう設定しています。
次に、リポジトリ内の「dry-runs」ディレクトリから、最新のスイープ実行結果を検索します。もし該当するディレクトリが見つかった場合、その中にあるすべてのジョブ設定ファイル(config.yaml)のパスをリストアップし、生成された構成がどのように展開されているかを確認できます。
- srtctl の Python API をプログラム的に利用する方法
Python スクリプトで srtctl の機能を直接呼び出すことも可能です。まず、必要なモジュール(YAML 処理や設定読み込み、スイープ生成、テンプレート展開など)をインポートします。
「my-disagg.yaml」という設定ファイルを読み込み、モデル名、精度、使用 GPU タイプ、ノード構成(プレフィルとデコードのノード数)、GPU 密度、ベンチマークの種類やパラメータ(入力/出力シーケンス長、並列度)などを表示します。また、利用可能なベンチマークタイプ、精度レベル、GPU タイプの列挙型一覧も出力できます。
さらに、YAML ファイルからスイープ設定を読み込み、プログラム上でジョブ構成を生成・展開する処理を実行します。これにより、各パラメータ組み合わせがどのようにマッピングされ、最終的なジョブ設定(例:チャンク化プレフィルサイズや最大トークン数)が決定されるかを詳細に確認できます。
最後に、テンプレート置換のデモンストレーションとして、変数を指定した値で置き換える処理を実行し、その結果を表示します。これにより、スクリプト内で動的な設定生成が行われている様子を把握できます。
例の パラメータスイープを実行し、その直積探索空間から生成された個々のジョブ構成を確認します。カスタムレシピを型付き Python API を通じて読み込み、対象モデル、精度設定、GPU トポロジ、ベンチマーク設定、およびサポートされる列挙値を検証します。また、プログラムによってスイープテンプレートを展開し、各パラメータの組み合わせが生成されるバックエンド構成にどのような影響を与えるかを検証します。
- 分析:(シミュレーションされた)ベンチマーク結果から見るパレートフロンティア
Python の NumPy と Matplotlib を用いて、異なる設定におけるスループットとレイテンシのトレードオフを可視化します。ここでは、コンカレンシー(同時処理数)を変えた際の性能変化をシミュレーションし、最適な構成を見極めるためのパレートフロンティアを描画しています。
まず、simulate 関数は、特定のバリアント(設定)とベースライン値(スループット base_tps、レイテンシ base_itl)を受け取り、ランダムな変動を加えながら複数のデータポイントを生成します。GPU あたりのトークン処理速度(TPS)は、コンカレンシー c が増えるほど低下する傾向を示し、トークン間遅延(ITL)は逆に増加します。これに ±3% のランダムノイズを付与することで、実際のベンチマークで観測されるようなばらつきを再現しています。
次に、2 つの異なる設定(chunked=4096 と chunked=8192)に対してシミュレーションを実行し、結果を結合します。各データポイントには、コンカレンシー値がラベルとして付与されます。
可視化では、横軸に「トークン間遅延(ms/token)」、縦軸に「スループット(tokens/s/GPU)」をとります。横軸は右に行くほど性能が悪く、縦軸は上に行くほど性能が良いことを示しています。各バリアントのデータ点をプロットし、コンカレンシーごとの値をラベルとして表示することで、どの設定が最も効率的なパフォーマンスを発揮しているかを直感的に把握できます。
このグラフから、特定のコンカレンシーにおいて、他の設定よりも劣らない性能(遅延も低く、スループットも高い)を持つ点を見つけることができます。これがパレート最適解であり、システム設計における重要な指針となります。
2 つのチャンク事前処理バリアントについて、並行度レベルを段階的に高めた際のベンチマーク観測値をシミュレーションします。GPU あたりの代表 throughput とトークン間レイテンシを算出し、分散型サービスシステムで一般的に観察される飽和現象とレイテンシの増大傾向をモデル化します。その後、これらの結果をパレート型のプロットとして可視化し、各構成におけるスループットと応答性の比較を行います。
section("9. 実機クラスタでの次のステップ")
print(textwrap.dedent("""\
make setup ARCH=aarch64|x86_64
srtctl preflight -f my-disagg.yaml
srtctl apply -f my-disagg.yaml
srtctl apply -f sweep.yaml
srtctl monitor
uv run streamlit run analysis/dashboard/app.py
srtctl diff runA runB
Logs land in outputs/{JOB_ID}/logs/; analysis/srtlog parses them
(NodeAnalyzer, RunLoader) for programmatic post-processing.
Reproducibility tip (srtctl also prints this in dry-run): add an
identity: block to your recipe — HF model repo + revision, container
image URI, and framework versions — so srtctl can verify the runtime
matches your declaration at job start.
"""))
print("
image Tutorial complete.")
ここでは、Colab で検証済みのレシピを実際の SLURM ベースの GPU クラスターへ移行する際のプロダクションワークフローを解説します。環境構築や事前チェック、ジョブの提出、パラメータスイープの実行、監視、ダッシュボード分析、そして実験結果の比較に用いるコマンドを確認していきます。また、各ベンチマークレシピ内でモデルのリビジョン、コンテナの識別情報、フレームワークのバージョンを明記することで、再現性を確保することにも重点を置いています。
結論として、srtctl がどのようにして分散 LLM サービングのベンチマークを構築し、検証・拡張・準備し、SLURM インフラ上で実行可能にするのかについて、包括的な理解を得ることができました。基本的なインストールやリポジトリの確認から始まり、非集約型サービング構成、カルテシアンパラメータスイープ、プログラムによるスキーマアクセス、そしてベンチマーク結果の分析へとステップアップしました。さらに、ドライラン(事前実行)によって生成されるジョブアーティファクトを確認し、高価なクラスターリソースを割り当てる前に設定上の問題を早期に発見できる仕組みも確認できました。
このワークフローが確立されれば、検証済みのレシピを実際の NVIDIA GPU クラスターへ自信を持って移行できます。事前チェックの実行、ベンチマークジョブの提出、実行状況の監視、実験ごとの指紋(フィンガープリント)比較、そして再現性のあるパフォーマンストレードオフの分析が可能になります。
完全なコードはこちらで確認できます。Twitter でフォローすることも可能ですし、15 万人以上の ML 関連ユーザーが参加する SubReddit にもぜひご参加ください。また、ニュースレターの購読も忘れずに。あ、Telegram も利用していますか?Telegram でも私たちに参加できるようになりました。
GitHub リポジトリや Hugging Face ページ、製品リリース、ウェビナーなどのプロモーションをご希望の場合は、ぜひパートナーシップを構築しましょう。お気軽にご連絡ください。
本記事「NVIDIA srt-slurm、SLURM レシピ、パラメータスイープ、パレート分析を用いた分散 LLM サービングベンチマークの検証」は、MarkTechPost で公開されたものです。
原文を表示
In this tutorial, we explore NVIDIA’s srt-slurm framework and learn how we use srtctl to convert declarative YAML configurations into reproducible SLURM benchmark workflows for distributed LLM serving. We set up the project in Google Colab, inspect its internal architecture, define a cluster configuration, dry-run built-in and custom recipes, and model a disaggregated prefill-and-decode deployment for DeepSeek-R1. We also generate parameter sweeps, interact with the typed Python API, validate expanded configurations, and analyze simulated benchmark results through a throughput-versus-latency Pareto frontier. Although Colab does not provide a real SLURM environment, we use it as a practical development workspace to understand, validate, and prepare production-grade benchmark recipes before we submit them to an actual GPU cluster.
Copy CodeCopiedUse a different Browser
import os, sys, subprocess, textwrap, json, shutil, importlib
from pathlib import Path
def run(cmd, check=True, quiet=False):
"""Run a shell command, stream output."""
print(f"\n$ {cmd}")
r = subprocess.run(cmd, shell=True, text=True, capture_output=True)
out = (r.stdout or "") + (r.stderr or "")
if not quiet:
print(out[-6000:])
if check and r.returncode != 0:
raise RuntimeError(f"Command failed ({r.returncode}): {cmd}")
return out
def section(title):
print("\n" + "═"*78 + f"\n {title}\n" + "═"*78)
section("1. Install srt-slurm")
REPO = Path("/content/srt-slurm") if Path("/content").exists() else Path.cwd()/"srt-slurm"
if not REPO.exists():
run(f"git clone --depth 1 https://github.com/NVIDIA/srt-slurm.git {REPO}", quiet=True)
run(f"{sys.executable} -m pip install -q -e {REPO}", quiet=True)
sys.path.insert(0, str(REPO / "src"))
importlib.invalidate_caches()
os.chdir(REPO)
run("srtctl --help")
We prepare the Colab environment by importing the required modules and defining reusable helper functions for command execution and section formatting. We clone the NVIDIA srt-slurm repository, install it in editable mode, and expose its source directory to the active Python runtime. We then switch to the repository directory and verify that the srtctl command-line interface is installed correctly.
Copy CodeCopiedUse a different Browser
section("2. Repository architecture")
print(textwrap.dedent("""
src/srtctl/
cli/ submit.py (apply/dry-run/preflight/monitor), do_sweep, interactive
core/ schema.py (typed config), sweep.py, slurm.py (sbatch gen),
validation.py, health.py, topology.py, fingerprint.py
backends/ sglang.py, trtllm.py, vllm.py, mocker.py ← engine adapters
frontends/ Dynamo / router frontends
templates/ Jinja2 → sbatch + orchestrator scripts
recipes/ ready-made benchmarks per platform (gb200-fp4, h100, b200-fp8,
qwen3-32b, dsv4-pro, mocker smoke tests, ...)
analysis/ srtlog (log parsers) + Streamlit dashboard (Pareto, latency...)
docs/ sweeps.md, profiling.md, analyzing.md, config-reference.md
"""))
for d in ["recipes", "docs"]:
print(f"{d}/ →", ", ".join(sorted(p.name for p in (REPO/d).iterdir()))[:300])
section("3. Cluster configuration (srtslurm.yaml)")
(REPO/"srtslurm.yaml").write_text(textwrap.dedent("""\
cluster: "colab-demo"
default_account: "demo-account"
default_partition: "gpu"
default_time_limit: "01:00:00"
gpus_per_node: 4
use_gpus_per_node_directive: true
use_segment_sbatch_directive: true
containers:
dynamo-sglang: "/containers/dynamo-sglang.sqsh"
lmsysorg+sglang+v0.5.5.post2.sqsh: "/containers/sglang-v0.5.5.sqsh"
model_paths:
deepseek-r1: "/models/DeepSeek-R1"
"""))
print((REPO/"srtslurm.yaml").read_text())
We inspect the repository structure to understand how srtctl organizes its command-line tools, schemas, backends, templates, recipes, and analysis components. We then create a local srtslurm.yaml file containing simulated cluster defaults, container aliases, GPU settings, and model paths. We use this configuration to resolve recipe references in Colab without requiring access to an actual SLURM cluster.
Copy CodeCopiedUse a different Browser
section("4. Dry-run: mocker smoke test → generated sbatch script")
run("srtctl dry-run -f recipes/mocker/agg.yaml", check=False)
section("5. Custom disaggregated recipe (prefill/decode split)")
(REPO/"my-disagg.yaml").write_text(textwrap.dedent("""\
name: "colab-disagg-demo"
model:
path: "deepseek-r1"
container: "lmsysorg+sglang+v0.5.5.post2.sqsh"
precision: "fp8"
resources:
gpu_type: "gb200"
gpus_per_node: 4
prefill_nodes: 1
decode_nodes: 2
prefill_workers: 1
decode_workers: 2
backend:
prefill_environment: { PYTHONUNBUFFERED: "1" }
decode_environment: { PYTHONUNBUFFERED: "1" }
sglang_config:
prefill:
served-model-name: "deepseek-ai/DeepSeek-R1"
model-path: "/model/"
trust-remote-code: true
kv-cache-dtype: "fp8_e4m3"
tensor-parallel-size: 4
disaggregation-mode: "prefill"
decode:
served-model-name: "deepseek-ai/DeepSeek-R1"
model-path: "/model/"
trust-remote-code: true
kv-cache-dtype: "fp8_e4m3"
tensor-parallel-size: 4
disaggregation-mode: "decode"
benchmark:
type: "sa-bench"
isl: 1024
osl: 1024
concurrencies: [64, 128, 256]
req_rate: "inf"
"""))
run("srtctl dry-run -f my-disagg.yaml", check=False)
We dry-run the built-in mocker recipe to examine how srtctl validates configurations and generates SLURM submission artifacts without executing a real benchmark. We then define an advanced DeepSeek-R1 recipe that separates prefill and decode workloads across independent node and worker pools. We validate this disaggregated SGLang configuration through another dry run and inspect how the serving parameters are translated into job scripts.
Copy CodeCopiedUse a different Browser
section("6. Parameter sweep (grid search) — dry-run + expansion on disk")
run("srtctl dry-run -f examples/example-sweep.yaml", check=False)
sweep_dirs = sorted((REPO/"dry-runs").glob("example-sweep_sweep_*"))
if sweep_dirs:
latest = sweep_dirs[-1]
print("Per-job configs generated by the sweep expander:")
for p in sorted(latest.rglob("config.yaml")):
print(" ", p.relative_to(REPO))
section("7. Programmatic use of srtctl's Python API")
import yaml
from srtctl.core.config import load_config
from srtctl.core.sweep import generate_sweep_configs, expand_template
from srtctl.core.schema import BenchmarkType, Precision, GpuType
cfg = load_config("my-disagg.yaml")
print(f"Loaded : {cfg.name}")
print(f"Model : {cfg.model.path} ({cfg.model.precision}) on {cfg.resources.gpu_type}")
print(f"Layout : {cfg.resources.prefill_nodes}P + {cfg.resources.decode_nodes}D nodes, "
f"{cfg.resources.gpus_per_node} GPUs/node")
print(f"Bench : {cfg.benchmark.type} isl={cfg.benchmark.isl} osl={cfg.benchmark.osl} "
f"concurrencies={cfg.benchmark.concurrencies}")
print(f"Enums : benchmarks={[b.value for b in BenchmarkType]}")
print(f" precisions={[p.value for p in Precision]}, gpus={[g.value for g in GpuType]}")
raw_sweep = yaml.safe_load(Path("examples/example-sweep.yaml").read_text())
jobs = generate_sweep_configs(raw_sweep)
print(f"\nSweep expands to {len(jobs)} jobs:")
for job_cfg, params in jobs:
pf = job_cfg["backend"]["sglang_config"]["prefill"]
print(f" {params} → chunked-prefill-size={pf['chunked-prefill-size']}, "
f"max-total-tokens={pf['max-total-tokens']}")
print("\nTemplate substitution:",
expand_template({"flag": "{x}", "n": "{y}"}, {"x": 4096, "y": 2}))
We execute the example parameter sweep and inspect the individual job configurations created from its Cartesian search space. We load our custom recipe through the typed Python API and examine its model, precision, GPU topology, benchmark settings, and supported enumeration values. We also programmatically expand sweep templates and verify how each parameter combination affects the generated backend configuration.
Copy CodeCopiedUse a different Browser
section("8. Analysis: Pareto frontier from (simulated) benchmark results")
import numpy as np, matplotlib.pyplot as plt
rng = np.random.default_rng(0)
def simulate(variant, base_tps, base_itl):
rows = []
tps_gpu = base_tps * c / (c + 90) * rng.uniform(.97, 1.03)
itl = base_itl * (1 + c/220) * rng.uniform(.97, 1.03)
rows.append({"variant": variant, "concurrency": c,
"tok_s_gpu": tps_gpu, "itl_ms": itl})
return rows
results = simulate("chunked=4096", 260, 9.5) + simulate("chunked=8192", 300, 11.5)
print(json.dumps(results[:3], indent=2), "...")
plt.figure(figsize=(8, 5))
for variant in ("chunked=4096", "chunked=8192"):
pts = [(r["itl_ms"], r["tok_s_gpu"], r["concurrency"])
for r in results if r["variant"] == variant]
xs, ys, cs = zip(*pts)
plt.plot(xs, ys, "o-", label=variant)
for x, y, c in pts:
plt.annotate(str(c), (x, y), fontsize=7, xytext=(3, 3),
textcoords="offset points")
plt.xlabel("Inter-token latency (ms/token) → worse")
plt.ylabel("Throughput (tokens/s/GPU) → better")
plt.title("Pareto frontier: sweep variants (points labeled by concurrency)")
plt.legend(); plt.grid(alpha=.3); plt.tight_layout(); plt.show()
We simulate benchmark observations for two chunked-prefill variants across increasing concurrency levels. We calculate representative throughput per GPU and inter-token latency values to model the saturation and latency growth commonly observed in distributed serving systems. We then visualize these results in a Pareto-style plot to compare throughput and responsiveness across configurations.
Copy CodeCopiedUse a different Browser
section("9. Next steps on a real cluster")
print(textwrap.dedent("""\
make setup ARCH=aarch64|x86_64
srtctl preflight -f my-disagg.yaml
srtctl apply -f my-disagg.yaml
srtctl apply -f sweep.yaml
srtctl monitor
uv run streamlit run analysis/dashboard/app.py
srtctl diff runA runB
Logs land in outputs/{JOB_ID}/logs/; analysis/srtlog parses them
(NodeAnalyzer, RunLoader) for programmatic post-processing.
Reproducibility tip (srtctl also prints this in dry-run): add an
identity: block to your recipe — HF model repo + revision, container
image URI, and framework versions — so srtctl can verify the runtime
matches your declaration at job start.
"""))
print("
image Tutorial complete.")
We outline the production workflow that we follow when transferring validated recipes from Colab to a real SLURM-based GPU cluster. We review the commands used for environment setup, preflight validation, job submission, sweep execution, monitoring, dashboard analysis, and experiment comparison. We also emphasize reproducibility by declaring model revisions, container identities, and framework versions inside each benchmark recipe.
In conclusion, we built a complete understanding of how srtctl structures, validates, expands, and prepares distributed LLM-serving benchmarks for execution on SLURM infrastructure. We moved from basic installation and repository inspection to advanced disaggregated serving configurations, Cartesian parameter sweeps, programmatic schema access, and benchmark-result analysis. We also saw how dry runs expose generated job artifacts and help us detect configuration problems before expensive cluster resources are allocated. With this workflow in place, we can confidently transfer our validated recipes to a real NVIDIA GPU cluster, run preflight checks, submit benchmark jobs, monitor execution, compare experiment fingerprints, and analyze performance trade-offs in a reproducible manner.
Check out the Full Code here. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Validating Distributed LLM Serving Benchmarks with NVIDIA srt-slurm, SLURM Recipes, Parameter Sweeps, and Pareto Analysis appeared first on MarkTechPost.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み