Skip to content

Add Nsight trace analysis to profiling tools - #2878

Open
Silas-Asamoah wants to merge 5 commits into
roboflow:mainfrom
Silas-Asamoah:feat/nsight-trace-analysis
Open

Add Nsight trace analysis to profiling tools#2878
Silas-Asamoah wants to merge 5 commits into
roboflow:mainfrom
Silas-Asamoah:feat/nsight-trace-analysis

Conversation

@Silas-Asamoah

@Silas-Asamoah Silas-Asamoah commented Aug 26, 2026

Copy link
Copy Markdown

Summary

This adds a scriptable analysis step for traces produced by the profiling harness.

  • Run nsys stats against an existing .nsys-rep trace and export the nvtx_pushpop_trace and nvtx_gpu_proj_trace reports as CSV.
  • Parse host-side NVTX ranges and per-instance GPU-projected ranges into a versioned analysis.json file linked to the run manifest.
  • Identify measured iterations as direct children of the capture range and join host and GPU records by process, thread, and range ID. Target instrumentation can reuse names such as iteration 0 without being misclassified.
  • Validate the exact iteration index set declared by the manifest and report missing or unexpected indexes.
  • Report per-iteration host inclusive time, host exclusive time, and GPU-projected time without combining their different timing semantics.
  • Document the analysis command, generated artifacts, timing caveats, and error behavior.
  • Create the run directory before starting Nsight so the trace is stored beside its manifest.

Why

The profiling harness records structured NVTX ranges in an Nsight Systems trace, but reviewing those traces requires the desktop UI or manual report commands. This change provides a repeatable command that produces machine-readable summaries while preserving links to the source trace, manifest, Git commit, and Nsight version.

Run the analysis with:

PYTHONPATH=. uv run python development/profiling/analyze.py \
  --run-dir inference_profiling/<profile>/runs/<run-id>

Testing

  • PYTHONPATH=. .venv/bin/python -m pytest tests/development/profiling -q (26 passed)
  • Black check on the changed profiling and test modules
  • isort check on the changed profiling and test modules
  • flake8 --select=E9,F63,F7,F82 on all changed Python modules
  • End-to-end smoke capture and analysis on an NVIDIA A100 80 GB with Nsight Systems 2025.1.3
    • Generated trace.nsys-rep, both CSV reports, and analysis.json
    • Matched two host iterations to two GPU-projected iterations
    • Produced no analysis warnings
  • End-to-end collision capture with a target range also named iteration 0
    • Preserved harness iterations 0 and 1
    • Kept all four identically named target ranges in the general host and GPU summaries
    • Produced no analysis warnings

Scope

This change does not add performance regression thresholds. It exports measurements and provenance so threshold or comparison policies can be added separately.

Export NVTX host and GPU projection reports through an argument-safe subprocess boundary. Parse sanitized Nsight 2025.1 fixtures while preserving raw and normalized range names.
Summarize host-inclusive, host-exclusive, and GPU-projected NVTX timings without conflating their semantics. Link the stable analysis.json artifact to its manifest, trace, reports, and Nsight version.
Explain the analysis command, generated artifacts, and host-versus-GPU timing semantics. Add an agent workflow for interpreting results without overstating regressions.
Prefix the copy-and-paste profiling command with mkdir -p so Nsight writes the trace beside its manifest instead of falling back to a temporary path.
@CLAassistant

CLAassistant commented Aug 26, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fba24e1d51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread development/profiling/analysis.py
Comment thread development/profiling/analysis.py Outdated
Use per-instance GPU projection traces and join host and GPU ranges by process, thread, and range ID. Validate the exact manifest iteration index set and cover target range name collisions.

@dkosowski87 dkosowski87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Silas,

Nice contribution! A really good starting point for a further detailed trace analysis. I left some smaller comments. Let's resolve those and merge this 🚀

command.extend(["--seed", str(config.seed)])

nsys_command = " \\\n ".join(_quote_nsys_command_part(part) for part in command)
mkdir_command = " ".join(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just use pathlib here to create a nested directory if it doesn't exist

"""Analyze one profiling run and write ``analysis.json``."""
manifest_path = run_dir / "manifest.yaml"
manifest = _load_manifest(manifest_path)
resolved_trace_path = trace_path or run_dir / "trace.nsys-rep"

@dkosowski87 dkosowski87 Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the independent trace_path with run_dir / "trace.nsys-rep"? We can prove provenance as we have run_dir / "manifest.yaml". Allowing for independent trace_path gives the user the opportunity to make a mistake.

raise NsysStatsError(f"Could not read Nsight report {path}: {error}") from error

if not rows:
raise NsysStatsError(f"Nsight report contains no rows: {path}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could fail for parse_nvtx_gpu_projection_trace when none of the nvtx ranges have attributable GPU work, while still the other report may be valid - we just measured CPU work.

*,
trace_path: Path,
output_dir: Path,
executable: str = "nsys",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor. Wondering whether we should add a version check here, perhaps with only a warning. The column names in the stat files are hardcoded, so we might fail on future major version bumps, although of course those might also change commands themselves.

class GpuProjectedRange:
"""GPU work projected from one NVTX range instance."""

name: str

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explicitly use here a key scoped name. So instead resize we use preprocessing.resize and postprocessing.resize omitting the iteration. So we don't aggregate a resize that is being used under two different operations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants