Skip to content

Commit 0613028

Browse files
authored
Migrate nsight-python to use NCU's dynamic injection loading feature; 1.0.0 release updates (#48)
Signed-off-by: Alok Joshi <aljoshi@nvidia.com>
1 parent e7d1787 commit 0613028

18 files changed

Lines changed: 576 additions & 416 deletions

‎README.md‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,3 @@ Review the [CONTRIBUTING.md](Contributing.md) file for information on how to con
6060
## License
6161

6262
All files hosted in this repository are subject to the [Apache 2.0](LICENSE) license.
63-
64-
## Disclaimer
65-
66-
nsight-python is in a Beta state. Beta products may not be fully functional, may contain errors or design flaws, and may be changed at any time without notice. We appreciate your feedback to improve and iterate on our Beta products.

‎docs/source/_static/switcher.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
"version": "latest",
44
"url": "https://docs.nvidia.com/nsight-python/"
55
},
6+
{
7+
"version": "1.0.0",
8+
"url": "https://docs.nvidia.com/nsight-python/1.0.0/"
9+
},
610
{
711
"version": "0.9.6",
812
"url": "https://docs.nvidia.com/nsight-python/0.9.6/"

‎docs/source/index.rst‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ Welcome to the Nsight Python documentation!
2828
release_notes/release_notes
2929
release_notes/known_issues
3030
release_notes/support
31-
release_notes/disclaimer
3231

3332

3433
.. toctree::

‎docs/source/installation/runtime_requirements.rst‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,15 @@
44
Runtime Requirements
55
=====================
66

7-
* **NVIDIA Nsight Compute from CUDA toolkit 12.0+**: nsight-python uses NVIDIA Nsight Compute CLI(ncu). Please make sure that ncu version 2022.4.0 or later is installed and available in the system path.
7+
* **NVIDIA Nsight Compute from CUDA Toolkit 13.3 Update 1 or later**: nsight-python uses the NVIDIA Nsight Compute CLI (ncu 2026.2.1+). Ensure ``ncu`` is installed and available on the system path.
8+
9+
Import Ordering
10+
---------------
11+
12+
``import nsight`` must come before:
13+
14+
* **CUDA initialization**: You must import nsight before any operation that initializes CUDA (e.g. ``torch.cuda.init()``). If CUDA is initialized first, NVIDIA Nsight Compute cannot attach correctly and profiling fails (commonly with ``NV_INJ_ERROR_NOT_INITIALIZED``).
15+
16+
**Recommendation**: Place ``import nsight`` at the top of your script, before all CUDA-related imports and calls.
17+
18+
* **Any NVTX API calls**: nsight-python updates ``NVTX_INJECTION64_PATH`` at import time. Any NVTX usage before ``import nsight`` will cause NVTX annotation ranges to be missed and profiling results to be incomplete.

‎docs/source/release_notes/disclaimer.rst‎

Lines changed: 0 additions & 7 deletions
This file was deleted.

‎docs/source/release_notes/known_issues.rst‎

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,6 @@
44
Known Issues
55
============
66

7-
- Nsight Python launches the application python script again with NVIDIA Nsight Compute CLI (ncu) for each ``@nsight.analyze.kernel`` decorator.
8-
9-
- Due to this issue, using ``nsight-python`` in interactive notebook environments
10-
(e.g., Jupyter Notebook or Google Colab) is not supported. Refer to
11-
`GitHub issue #3 <https://github.com/NVIDIA/nsight-python/issues/3>`_
12-
for more information..
13-
14-
In the meantime, you can use the following workaround by placing your benchmark
15-
into a standalone Python script and executing it outside the interactive cell environment::
16-
17-
%%writefile quickstart.py
18-
import torch
19-
import nsight
20-
21-
@nsight.analyze.kernel
22-
def benchmark_matmul(n):
23-
"""
24-
The simplest possible benchmark.
25-
We create two matrices and multiply them.
26-
"""
27-
# Create two NxN matrices on GPU
28-
a = torch.randn(n, n, device="cuda")
29-
b = torch.randn(n, n, device="cuda")
30-
31-
# Mark the kernel we want to profile
32-
with nsight.annotate("matmul"):
33-
c = a @ b
34-
35-
return c
36-
37-
result = benchmark_matmul(1024)
38-
39-
Then run the script with::
40-
41-
%run quickstart.py
42-
437
- Kernels launched from a subprocess which is created within the annotated region will not be profiled.
448
- For the ``nsight.analyze.kernel``'s ``replay_mode="range"`` option, only a subset of CUDA APIs are supported within the annotated range. If an unsupported API call is detected, an error will be reported. For details on supported APIs, refer to the `NVIDIA Nsight Compute Profiling Guide <https://docs.nvidia.com/nsight-compute/ProfilingGuide/index.html#supported-apis>`_. In such cases, you can either switch to ``replay_mode="kernel"`` or modify the code to exclude the unsupported API from the annotated range.
459
- Nested annotations (using ``nsight.annotate`` within another ``nsight.annotate`` context) are not supported. nsight-python errors out when nested annotations are used.

‎docs/source/release_notes/release_notes.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ Release Notes
77
.. toctree::
88
:maxdepth: 2
99

10+
topics/updates-in-nsight-python-1.0.0
1011
topics/updates-in-nsight-python-0.9.6
1112
topics/updates-in-nsight-python-0.9.5
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
.. SPDX-License-Identifier: Apache-2.0
3+
4+
Updates in Nsight Python 1.0.0
5+
==============================
6+
7+
Enhancements
8+
------------
9+
10+
- **Eliminated per-decorator Python script relaunch**: Previously, nsight-python
11+
relaunched the entire Python script once for each :func:`@nsight.analyze.kernel <nsight.analyze.kernel>` decorated
12+
function in order to collect profiles using NVIDIA Nsight Compute. nsight-python now
13+
dynamically loads NVIDIA Nsight Compute's CUDA injection library at import time and uses
14+
``ncu --mode attach`` to attach to the running Python process, with no script relaunch.
15+
This reduces profiling overhead and avoids relaunch-related side effects from
16+
re-running module/import-time code.
17+
Interactive environments such as Jupyter Notebook and Google Colab are now supported
18+
(fixes `#3 <https://github.com/NVIDIA/nsight-python/issues/3>`_ and `#19 <https://github.com/NVIDIA/nsight-python/issues/19>`_).
19+
20+
- **Added support for metric units**: The DataFrame returned by
21+
:meth:`~nsight.collection.core.ProfileResults.to_dataframe` now includes a ``Unit`` column. Units for
22+
metrics collected with NVIDIA Nsight Compute are parsed directly from the report. For derived
23+
metrics, ``derive_metric`` should return a ``(value, unit)`` tuple for a single
24+
metric, or a dictionary of ``(value, unit)`` tuples for multiple metrics. Returning
25+
only the value remains supported for backward compatibility, but emits a warning and
26+
sets ``Unit`` to ``np.nan``.
27+
28+
- **Improved decorated function parameter handling**
29+
(`#31 <https://github.com/NVIDIA/nsight-python/pull/31>`_):
30+
31+
- **Keyword-only parameters** (defined after ``*`` in the signature) are now
32+
supported. Config values are mapped correctly to both positional and keyword-only
33+
parameters.
34+
- **Default parameter values**: configs can now omit trailing parameters that have
35+
defaults — missing values are filled in automatically from the function signature.
36+
- ``*args`` / ``**kwargs`` no longer cause false validation errors; they are
37+
excluded from parameter counting and ignored during profiling.
38+
39+
- **Added cuTile kernel example**
40+
(`#37 <https://github.com/NVIDIA/nsight-python/pull/37>`_):
41+
Added a new example demonstrating how to profile a CUDA Tile kernel.
42+
43+
API Changes
44+
-----------
45+
46+
- **Replaced** ``output`` **with** ``verbosity``: The ``output`` parameter of
47+
:func:`@nsight.analyze.kernel <nsight.analyze.kernel>`, which accepted the strings
48+
``"quiet"``, ``"progress"``, and ``"verbose"``, has been replaced by a
49+
``verbosity`` parameter of type :class:`~nsight.utils.VerbosityLevel`:
50+
51+
- ``VerbosityLevel.SILENT`` (replaces ``"quiet"``): suppresses all output.
52+
- ``VerbosityLevel.INFO`` (replaces ``"progress"``): shows the progress bar,
53+
profiling completion messages, and report file paths. This is the default.
54+
- ``VerbosityLevel.DEBUG`` (replaces ``"verbose"``): additionally prints the
55+
full NCU CLI command and enables NCU verbose output.
56+
57+
Fixes
58+
-----
59+
60+
- **Fixed crashes with tuple-valued function arguments**
61+
(`#30 <https://github.com/NVIDIA/nsight-python/pull/30>`_):
62+
Fixed crashes and corrupted extraction results when profiled functions have
63+
tuple-valued arguments. Tuple arguments are now preserved correctly for
64+
single- and multi-metric profiling.
65+
66+
- **Fixed crashes with unhashable config parameters**
67+
(`#42 <https://github.com/NVIDIA/nsight-python/pull/42>`_):
68+
Fixed crashes when aggregating profiling results for configurations containing
69+
dictionary- or list-valued arguments. These configuration parameters are now
70+
handled consistently regardless of the number of runs.

‎nsight/__init__.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55

66
from nsight import analyze
77
from nsight.annotation import annotate
8+
from nsight.collection.ncu import try_init_injection
89
from nsight.utils import VerbosityLevel, col_panel, row_panel
910

11+
# Load injection library and symbols for NCU attach (if available)
12+
try_init_injection()
13+
1014
__version__ = version("nsight-python")
1115

1216
__all__ = ["analyze", "annotate", "VerbosityLevel"]

‎nsight/analyze.py‎

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,11 @@ def _create_profiler() -> collection.core.NsightProfiler:
297297
"""Helper to create the profiler with the given settings."""
298298
# Create the output paths needed for the ncu report, ncu logs and the CSVs
299299
prefix = output_prefix
300-
if "NSPY_NCU_PROFILE" not in os.environ:
301-
if prefix is None:
302-
prefix = tempfile.mkdtemp(prefix="nspy_")
303-
prefix = os.path.join(
304-
prefix, ""
305-
) # Adds a trailing forward/backward slash
306-
else:
307-
os.makedirs(os.path.dirname(prefix) or ".", exist_ok=True)
300+
if prefix is None:
301+
prefix = tempfile.mkdtemp(prefix="nspy_")
302+
prefix = os.path.join(prefix, "") # Adds a trailing forward/backward slash
303+
else:
304+
os.makedirs(os.path.dirname(prefix) or ".", exist_ok=True)
308305

309306
settings = collection.core.ProfileSettings(
310307
configs=configs,
@@ -476,30 +473,29 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
476473
def wrapper(*args: Any, **kwargs: Any) -> Any:
477474
result = func(*args, **kwargs)
478475

479-
if "NSPY_NCU_PROFILE" not in os.environ:
480-
# Legalize the user-provided metric for plotting
481-
legalized_metric = _legalize_metric(result, metric)
482-
483-
visualization.visualize(
484-
result.to_dataframe(),
485-
metric=legalized_metric,
486-
row_panels=row_panels,
487-
col_panels=col_panels,
488-
x_keys=x_keys,
489-
print_data=print_data,
490-
title=title,
491-
filename=filename,
492-
ylabel=ylabel or "",
493-
annotate_points=annotate_points,
494-
show_avg=show_avg,
495-
show_geomean=show_geomean,
496-
plot_type=plot_type,
497-
plot_width=plot_width,
498-
plot_height=plot_height,
499-
variant_fields=variant_fields,
500-
variant_annotations=variant_annotations,
501-
plot_callback=plot_callback,
502-
)
476+
# Legalize the user-provided metric for plotting
477+
legalized_metric = _legalize_metric(result, metric)
478+
479+
visualization.visualize(
480+
result.to_dataframe(),
481+
metric=legalized_metric,
482+
row_panels=row_panels,
483+
col_panels=col_panels,
484+
x_keys=x_keys,
485+
print_data=print_data,
486+
title=title,
487+
filename=filename,
488+
ylabel=ylabel or "",
489+
annotate_points=annotate_points,
490+
show_avg=show_avg,
491+
show_geomean=show_geomean,
492+
plot_type=plot_type,
493+
plot_width=plot_width,
494+
plot_height=plot_height,
495+
variant_fields=variant_fields,
496+
variant_annotations=variant_annotations,
497+
plot_callback=plot_callback,
498+
)
503499
return result
504500

505501
return wrapper

0 commit comments

Comments
 (0)