deepstream-profile-pipeline について
NVIDIA DeepStream の効率的なパイプラインを作成し、性能を測定するプロファイリングスキルです。推論スループットとハードウェア上限から設定を導き、Nsight Systems の CLI で全体とプラグインの時間を報告します。
主な機能
- 01性能重視のパイプライン既定値の適用
- 02推論バッチサイズのプラトー測定
- 03GPU 上限に基づく設定導出
- 04Nsight Systems CLI によるプロファイリング
- 05プラグイン別 NVTX 時間の報告
活用シーン
- 01目標ストリーム数に合わせた新規パイプラインの調整
- 02GPU と推論スループット上限の測定
- 03全体時間に影響するパイプライン段階の特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill deepstream-profile-pipelineインストール後、Claude Code で/deepstream-profile-pipelineを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdREADME.mdrequirements.txtskill-card.mdskill.oms.sigevals/evals.jsonreferences/boundedness-rules.mdconfig-derivation-rules.mdhw-ceiling-formulas.mdnsys-cli-recipes.mdnvtx-coverage.mdscripts/capacity_report.pytests/__init__.pyREADME.mdtest_capacity_report.py詳細
DeepStream プロファイリングスキル
プロファイルに基づくパイプラインの作成です。ユーザーが効率的な DeepStream パイプラインを求めている場合、このスキルは推測を 2 つの実測値(推論の飽和バッチサイズ と ハードウェア上限)に置き換え、その他すべての設定をそこから導き出します。さらに、Nsight Systems で E2E パイプラインをプロファイリングし、プラグインごとの NVTX タイミングを報告します。
モデルやパイプラインに依存しません。 このスキルが前提とするのは、推論要素が
nvinfer または nvinferserver であることだけです(モデルの次元、精度、バッチ関連の設定を標準の設定ファイルから変更できるためです)。検出(トラッカーあり、なしの両方)、分類、
セグメンテーション、VLM、埋め込みのパイプラインで動作します。ソースはファイル、RTSP、
USB カメラ、またはそれらの任意の組み合わせを使用できます。このスキルは、ユーザーの実際の設定ファイルからモデルの次元、目標 FPS、ソースのプロパティを確認します。特定のモデル、コーデック、解像度を
前提とすることはありません。
制約。 ターミナルのみを使用します。キャプチャには
nsys profileを、抽出にはnsys statsを使用します。 Nsight Lens や GUI には依存しないでください。
起動するタイミング
ユーザーの依頼に効率性を重視する意図がある場合は、パイプラインの作成時に このスキルを起動します。具体的な例:
- 「効率的な/高速な/高性能な/最適化されたパイプラインを作成して」
- 「この GPU で適切に動作するパイプラインをください」
- 「このパイプラインをベンチマーク/プロファイリング/測定/調整/最適化して」
- 「N 個のストリームを M FPS で実行したい」
- 「この GPU では何本のストリームを処理できますか」
nsysまたは Nsight を明示的に求めている
パフォーマンスを重視する意図がなく、単に「パイプラインを作成して」「この動画を表示して」
「このストリームを保存して」といった依頼の場合は、代わりに
deepstream-generate-pipeline スキルに引き継ぎます。
6 段階のフロー
各段階を順番に実行します。段階 0 はパイプラインの生成前に実行されるため、ユーザーは パフォーマンス調整済みのひな形から開始できます。段階 1~5 で測定と検証を行います。
ステージ 0 — プリセットの適用(パイプライン作成時)
トリガー:コーディングエージェントが新しい DS パイプラインを生成しようとしており、かつユーザーの プロンプトに効率化の意図が含まれている場合(上記の「トリガーする条件」を参照)。
アクション:以下のデフォルト値を、確認を求めずに事前適用します。ユーザーがこれらを知る必要はありません。 最適な形に整ったパイプラインを利用できます。
| 設定項目 | デフォルト値 | 適用しない条件 |
|---|---|---|
nvinfer.network-mode | int8-calib-file=<path> にキャリブレーションファイルが指定されている場合は 1(INT8)、それ以外は 2(FP16)。FP32 は使用しません。 | モデルに INT8 キャリブレーションファイルがなく、ユーザーが明示的に「FP32」と指定している場合。 |
nvinfer.model-engine-file | 事前ビルド済みの .engine パス | 常に設定します。計測前に一度だけ事前ビルドを強制します。 |
nvinfer.infer-dims | モデルのネイティブ入力に合わせた 3;<H>;<W> | 常に設定します。静的形状の ONNX でも問題ありません。 |
nvstreammux.batch-size | マイクロベンチマークで調整するまで min(N_streams, 16) | — |
nvstreammux.width / height | モデルのネイティブ入力サイズ(nvinfer の設定にある infer-dims=3;H;W から読み取る) | ユーザーが muxer でソースのネイティブ解像度を使うよう明示的に求めている場合。 |
nvstreammux.batched-push-timeout | 1e6 / source_fps µs(30 fps の場合は 33333) | — |
nvstreammux.nvbuf-memory-type | 0(NVMM) | — |
デコーダーの num-extra-surfaces | min(batch_size, 5) | — |
デコーダーの cudadec-memtype | 0(NVMM) | — |
| シンク | ベンチマーク用の構成では fakesink sync=False | ユーザーが画面表示またはディスクへの録画を求めている場合(その場合は OSD/tiler/エンコーダー/シンクを維持し、2 つのバリアントを作成します)。 |
| OSD + tiler | 省略します | ユーザーが出力の表示を求めている場合。 |
トラッカーの ll-config-file | config_tracker_NvDCF_max_perf.yml(DS 9.0 に付属する、パフォーマンス向けに調整済みの NvDCF プリセット) | トラッカーがない場合。 |
トラッカーの tracker-width / height | 480 / 288 | — |
トラッカーの enable-batch-process(リンクされた YAML 内) | 1 | — |
| ソースと pgie の間のキュー | max-size-buffers = batch_size × 4 | キューが要求されていない場合(まれ)。 |
| Kafka/メッセージキュー | max-size-buffers=2, leaky=2 | Kafka がない場合。 |
デコード側の PerfMonitor | アタッチします(pgie 側に加えて) | パイプラインが中間キューなしで nvurisrcbin → pgie に直結している場合。 |
**ステージ 0 がある理由:**これがないと、新しく生成されるパイプラインはすべて表示優先のデフォルト値から始まり、 ステージ 1~5 で回避可能な問題の修正に時間を費やすことになります。ステージ 0 は、 「最初から問題のあるパイプラインを書かない」ためのゲートです。
学生/API ユーザーには、これらの設定項目は表示されません。スキルからユーザーへの応答では、 設定項目名ではなく、平易な英語で FPS、ストリーム数、観測されたボトルネックを伝えます。
検証フロー(ステージ 1~5)
各ステージを順番に実行します。後続のステージは前のステージの出力に依存するため、ステージを省略しないでください。
ステージ 1 — NVTX カバレッジの確認
DeepStream プラグインは標準で NVTX レンジを出力しますが、カスタムプラグインとプレーンな GStreamer コア要素(queue、tee、h264parse など)は出力しません。プロファイリングの前に、パイプラインで使用する要素を列挙し、それぞれを分類します。
- パイプライン定義(gst-launch 文字列または
pipeline.py)を読み込みます。 - 各要素を references/nvtx-coverage.md で確認します。
- COVERED(この DS/イメージ/nsys の組み合わせで NVTX を出力する)または UNINSTRUMENTED に分類します。
- **MVP のルール:**スキルでは確認のためにプラグインごとの NVTX を優先しますが、必須ではありません。
デコードがボトルネックの場合はマイクロベンチマークの傾向と
nvidia-smi dmonから、 計算がボトルネックの場合は CUDA カーネルの構成から、メモリーコピーの場合はcuda_gpu_mem_time_sumから診断できます。NVTX はあれば有用です。 - UNINSTRUMENTED の要素については「このビルドでは直接測定できません」と報告し、 入力から導出される(プラグインごとのプロファイルデータには依存しない)閉形式の R1~R6 設定を引き続き適用します。
- インストルメントされていない要素への NVTX の自動挿入は、このバージョンのスコープ外です。 最終レポートで今後の対応事項として記載してください。
ステージ 1 の出力:以下のような簡潔なカバレッジ表
nvurisrcbin COVERED
nvstreammux COVERED
nvinfer COVERED
nvtracker COVERED
queue_src UNINSTRUMENTED — not re-tuned
fakesink UNINSTRUMENTED — not re-tuned
ステージ 2 — HW の検出
nvidia-smi を実行し、ホスト GPU の理論上の上限値を算出します。最低限必要なクエリ:
# Identity + memory + compute
nvidia-smi --query-gpu=name,compute_cap,memory.total,memory.free,\
clocks.max.sm,clocks.max.memory,utilization.gpu \
--format=csv,noheader,nounits
# NVDEC / NVENC utilization (per-engine)
nvidia-smi --query-gpu=utilization.decoder,utilization.encoder \
--format=csv,noheader,nounits
# PCIe link width/gen (for H2D memcpy ceiling)
nvidia-smi --query-gpu=pcie.link.gen.current,pcie.link.width.current \
--format=csv,noheader,nounits
これらの数値から以下を算出します。
- デコード上限(fps):NVDEC_count × ソース解像度における H265/H264 のユニットあたり fps (表は references/hw-ceiling-formulas.md を参照してください)。
- 演算上限(TOPS):SM 数 × クロック × 目標精度におけるクロックあたりの演算数。上限値を示します。実際のモデルではこの 30〜60%になります。
- メモリ帯域幅の上限(GB/s):メモリクロック × バス幅。モデルの重みの読み込みとアクティベーションは、この値を十分に下回る必要があります。
- Memcpy の上限(GB/s):PCIe 世代 × レーン幅 × 実効係数 0.8。NVMM に問題があり、ステージ 5 で H2D/D2H 転送が確認された場合にのみ関係します。
算出した上限値を保存してください。ステージ 5 の「実測値と理論値」のセクションで使用します。
完全な計算式とコーデック別の NVDEC スループット表: references/hw-ceiling-formulas.md。
ステージ 3 — 推論のみのマイクロベンチマーク
推論ステージのみ(ソース → streammux → nvinfer → fakesink)を実行し、batch-size を変えながら性能の頭打ちを確認します。これにより、他のすべての要素からモデル本来の最大 FPS を切り分け、「FPS を低下させずに単一のバッチに収められるストリーム数はいくつか?」という疑問に答えます。
試行範囲:batch-size ∈ {1, 2, 4, 8, 16, 32}(N_streams と GPU メモリの上限を適用します)。
各バッチサイズについて:
nvstreammux.batch-size = nvinfer.batch-size = Bを設定します。nvstreammux.width/heightをモデルのネイティブなinfer-dimsに設定します(nvinfer の設定から読み取ります)。- 分岐は
fakesink sync=Falseのみとします。 - 30 秒間実行し、
measure_fps_probe(コンソール)または DSPerfMonitorから FPS を測定します。 (B, fps)を記録します。
頭打ちとなるバッチサイズ = B を 2 倍にしても FPS の向上が 5%未満となる最小の B です。これを全パイプラインの目標バッチサイズとします。
ユーザーの N_streams が頭打ちとなるバッチサイズ以下の場合は、最終バッチサイズを N_streams に設定します。それを超える場合は、最終バッチサイズを頭打ちとなるバッチサイズに設定し、1 ティックあたりに複数のバッチでストリームを処理することを明記します。
ステージ 4 — 設定を導出
(plateau_batch, HW_ceilings, N_streams, source_res, source_fps) から、調整可能なすべてのパラメーターを一度に設定します。パラメーターを一つずつ調整しないでください。導出ルールは閉形式です。
設定するパラメーターは以下の順です。
- Streammux:
batch-size = final_batch、width/height = min(source_res, infer_dims)、batched-push-timeout = 1e6 / source_fpsµs、nvbuf-memory-type = 0。 - 推論:
batch-size = final_batch、キャリブレーションファイルが存在する場合はnetwork-mode = 1 (INT8)、そうでない場合は2 (FP16)、interval = 0、infer-dims = モデルのネイティブな dims、model-engine-file = ビルド済み .engine のパス。 - デコーダー(
nvurisrcbin/nvmultiurisrcbin/nvv4l2decoder上):num-extra-surfaces = min(final_batch, 5)、cudadec-memtype = 0、nvbuf-memory-type = 0。 - トラッカー(存在する場合):
enable-batch-process = 1、トラッカーの解像度は 480×288、ll-config-fileをconfig_tracker_NvDCF_max_perf.ymlに指定します。 - キュー(デコーダーと streammux の間、または streammux と nvinfer の間に存在する場合):
max-size-buffers = final_batch × 2。Kafka/メッセージの分岐:leaky=2, max-size-buffers=2。
各計算式と「理由」の一行説明を含む、完全な導出表: references/config-derivation-rules.md。
導出した値をユーザーの設定ファイル(pgie_config.yml、
tracker_config.yml、pipeline.py のソースプロパティ、deepstream-app の .txt ファイル)に書き込みます。必ず編集前に Read してください。編集は最小限にとどめ、無関係な行の書式は変更しないでください。
ステージ 5 — E2E プロファイルとレポート
nsys profile で E2E パイプラインを実行し、nsys stats でプラグインごとの処理時間を抽出します。
取得項目:
TS=$(date +%Y%m%d_%H%M%S)
OUT=/tmp/ds_profile_${TS}
nsys profile \
--trace=cuda,nvtx,osrt \
--gpu-metrics-devices=all \
--cuda-memory-usage=true \
--force-overwrite=true \
--duration=30 \
--output=${OUT} \
<your-pipeline-launch-command>
抽出項目:
# Per-kernel GPU time (top 10)
nsys stats --report cuda_gpu_kern_sum --format csv ${OUT}.nsys-rep | head -20
# Per-NVTX-range time (top 10) — this is the DS per-plugin breakdown
nsys stats --report nvtx_sum --format csv ${OUT}.nsys-rep | head -20
# Memcpy totals
nsys stats --report cuda_gpu_mem_time_sum --format csv ${OUT}.nsys-rep
# GPU metrics (SM activity, DRAM throughput) — requires --gpu-metrics-devices
nsys stats --report gpu_metric_gpu_util_sum --format csv ${OUT}.nsys-rep
コマンドの完全なリファレンス:references/nsys-cli-recipes.md。
レポート(Markdown、標準出力へ — 外部 UI は使用しません):
## Profile summary
**Hardware**: <name>, <mem_total> GB, SM x<sm>, NVDEC x<nvdec>, PCIe Gen<g> x<w>
**Ceilings**: decode <X> fps, compute ~<Y> TOPS @ INT8, memory <Z> GB/s
**Inference plateau**: batch=<B>, peak=<F> fps per batch → <F × B> fps aggregate
**E2E measured**: <actual> fps (=<pct>% of inference plateau)
### Per-plugin time (from NVTX) — only for plugins emitting NVTX in this build
| Plugin | Share of wall time | GPU / CPU | Notes |
|-----------------|--------------------|-----------|-------|
| nvinfer | <pct>% | GPU | (always emitted; if absent, NVTX injection is broken) |
| nvdsosd | <pct>% | GPU | (when in pipeline) |
| ... | ... | ... | (other plugins as the verification probe shows) |
(Numbers above are illustrative — fill in from `nsys stats --report nvtx_sum`. Plugins
that don't emit NVTX in your DS / image combo simply don't appear; that's not a bug, it's
the limit of what NVTX captures here. See `references/nvtx-coverage.md`.)
### Applied configs (sample shape; values come from R1–R6 + Stage 3 measurements)
- `nvstreammux.batch-size = <plateau_batch>`
- `nvinfer.network-mode = 1 (INT8)` if calibration available, else `2 (FP16)`
- decoder `num-extra-surfaces = min(plateau_batch, 5)`
- queue between source and pgie, `max-size-buffers = plateau_batch × 4`
- ... (full list per the user's pipeline shape)
### Uninstrumented (skipped re-tune)
List the elements that didn't emit NVTX in this build (typically the closed-source binary
plugins — see `references/nvtx-coverage.md`) plus plain GStreamer-core helpers. Report
them so the user knows what wasn't directly measurable.
要約は簡潔にしてください。nsys stats の生 CSV は応答ではなく、一時ファイルに保存します。
参考資料
| ドキュメント | 使用する場面 |
|---|---|
| references/nvtx-coverage.md | ステージ 1 — 各パイプライン要素を COVERED または UNINSTRUMENTED に分類します。 |
| references/hw-ceiling-formulas.md | ステージ 2 — nvidia-smi の出力をデコード/演算/メモリの上限値に変換します。 |
| references/config-derivation-rules.md | ステージ 4 — (plateau_batch, HW, N_streams, source_res, source_fps) をキーとするノブごとの計算式です。 |
| references/nsys-cli-recipes.md | ステージ 3 と 5 — nsys profile/nsys stats の正確な実行方法です。 |
対象外(このバージョン)
- Nsight Lens/GUI は使用しません。 ターミナルのみです。
- 計測されていないプラグインへの NVTX の自動挿入は行いません。 MVP では、それらのノブは対象外です。今後の対応予定です。
- 反復的な調整・計測・調整のループは行いません。 ステージ 4 では閉形式のルールから設定を一度導出し、ステージ 5 で計測して結果を報告します。ユーザーが調整を続けたい場合は、入力を更新してこのスキルを再度呼び出せます。
関連スキル
deepstream-generate-pipeline— 上流のパイプライン生成です。このスキルでは、パイプラインがすでに存在するか、これから生成されることを前提とします。deepstream-byovm— HF から TensorRT エンジンをビルドします。ユーザーが新しいモデルを持ち込んだ場合は先に実行し、その後こちらを実行してください。
注意事項
- リポジトリの
CLAUDE.mdにある規約に従い、ほかの DS スキルと並んでskills/deepstream-profile-pipeline/に配置されています。 - 任意のプラグインのプロパティ(型、デフォルト値、範囲)やパッドのケイパビリティを正確に確認するには、DS コンテナ内で読み込まれたバイナリを照会してください。
プラグインの命名規則:gst-inspect-1.0 nvinfer gst-inspect-1.0 nvstreammux gst-inspect-1.0 nvurisrcbin # works on closed-source binary plugins too gst-inspect-1.0 | grep ^nv # list every NVIDIA-specific element this build shipsnv*をプレフィックスとする要素は NVIDIA DeepStream 固有です(NVMM に対応し、NVTX を出力する場合があります)。それ以外は上流の GStreamer-core です(NVMM には対応せず、DS NVTX を出力することはありません)。見慣れないパイプラインを分類する際は、このプレフィックスを最初の判定基準として使用してください。 - プラグインコードのオープンソース部分は
/opt/nvidia/deepstream/deepstream/sources/gst-plugins/にあります(必要に応じて実装を確認できます。ただし、オープンソースなのは一部のプラグインのみです。非公開のプラグインはgst-inspect-1.0で検査し、実行時の動作を観察する必要があります)。