|
| 1 | +.. SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 2 | +.. SPDX-License-Identifier: Apache-2.0 |
| 3 | +
|
| 4 | +Tools |
| 5 | +===== |
| 6 | + |
| 7 | +Nsight Python collects its data through an underlying NVIDIA tool. Only one tool |
| 8 | +can be active at a time, and :func:`nsight.activate` selects and loads it. |
| 9 | + |
| 10 | +.. autofunction:: nsight.activate |
| 11 | + |
| 12 | +.. autofunction:: nsight.deactivate |
| 13 | + |
| 14 | +.. autofunction:: nsight.get_active_tool |
| 15 | + |
| 16 | +.. autoclass:: nsight.Tool |
| 17 | + |
| 18 | +Supported tools |
| 19 | +--------------- |
| 20 | + |
| 21 | +NVIDIA Nsight Compute |
| 22 | +^^^^^^^^^^^^^^^^^^^^^ |
| 23 | + |
| 24 | +:attr:`nsight.Tool.NCU` profiles individual kernels with the NVIDIA Nsight |
| 25 | +Compute CLI. It is the default tool for ``@nsight.analyze.kernel``. |
| 26 | + |
| 27 | +Activation |
| 28 | +"""""""""" |
| 29 | + |
| 30 | +NVIDIA Nsight Compute's injection library has to be loaded before CUDA is |
| 31 | +initialized. It is loaded in one of three ways. |
| 32 | + |
| 33 | +* **At import, by default.** ``import nsight`` activates NCU. |
| 34 | +* **Explicitly, for control over the timing.** Ensure the environment variable |
| 35 | + ``NSPY_NCU_INIT_AT_IMPORT`` is set to ``0`` before ``nsight`` is imported, |
| 36 | + then activate NCU where it suits you. Explicit activation also surfaces setup |
| 37 | + errors at that point. |
| 38 | + |
| 39 | + .. code-block:: python |
| 40 | +
|
| 41 | + import os |
| 42 | +
|
| 43 | + os.environ["NSPY_NCU_INIT_AT_IMPORT"] = "0" |
| 44 | +
|
| 45 | + import nsight |
| 46 | +
|
| 47 | + nsight.activate(nsight.Tool.NCU) |
| 48 | +
|
| 49 | +* **Lazily, on first use.** Under ``NSPY_NCU_INIT_AT_IMPORT=0``, the first call |
| 50 | + to a function decorated with ``@nsight.analyze.kernel`` loads the library. |
| 51 | + Ensure the first decorated call comes before any code that initializes CUDA. |
| 52 | + |
| 53 | +Limitations |
| 54 | +""""""""""" |
| 55 | + |
| 56 | +**Deactivation.** :func:`~nsight.deactivate` is not supported. The injection |
| 57 | +library cannot be unloaded, so NCU stays loaded for the lifetime of the process |
| 58 | +and remains the active tool once activated. |
| 59 | + |
| 60 | +.. _tools-cupti: |
| 61 | + |
| 62 | +NVIDIA CUPTI (experimental) |
| 63 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 64 | + |
| 65 | +:attr:`nsight.Tool.CUPTI` is an opt-in, low-overhead alternative for collecting |
| 66 | +kernel time durations, measured using CUPTI's Activity API. |
| 67 | + |
| 68 | +Activation |
| 69 | +"""""""""" |
| 70 | + |
| 71 | +To activate CUPTI, ensure the environment variable |
| 72 | +``NSPY_NCU_INIT_AT_IMPORT`` is set to ``0`` before ``nsight`` is imported: |
| 73 | + |
| 74 | +.. code-block:: python |
| 75 | +
|
| 76 | + import os |
| 77 | +
|
| 78 | + os.environ["NSPY_NCU_INIT_AT_IMPORT"] = "0" |
| 79 | +
|
| 80 | + import torch |
| 81 | +
|
| 82 | + import nsight |
| 83 | +
|
| 84 | + nsight.activate(nsight.Tool.CUPTI) |
| 85 | +
|
| 86 | +
|
| 87 | + @nsight.analyze.kernel |
| 88 | + def benchmark_matmul(n): |
| 89 | + a = torch.randn(n, n, device="cuda") |
| 90 | + b = torch.randn(n, n, device="cuda") |
| 91 | +
|
| 92 | + with nsight.annotate("matmul"): |
| 93 | + c = a @ b |
| 94 | +
|
| 95 | +
|
| 96 | + if __name__ == "__main__": |
| 97 | + result = benchmark_matmul(1024) |
| 98 | + print(result.to_dataframe()) |
| 99 | +
|
| 100 | + nsight.deactivate() |
| 101 | +
|
| 102 | +Activating CUPTI updates ``NVTX_INJECTION64_PATH``. Any NVTX usage before |
| 103 | +``nsight.activate(nsight.Tool.CUPTI)`` will cause NVTX annotation ranges to be |
| 104 | +missed and profiling results to be incomplete. |
| 105 | + |
| 106 | +CUPTI may be activated either before or after CUDA is initialized. |
| 107 | + |
| 108 | +Limitations |
| 109 | +""""""""""" |
| 110 | + |
| 111 | +**Platform.** Linux only for now. |
| 112 | + |
| 113 | +**Metrics.** Only ``"gpu__time_duration.sum"`` is supported. CUPTI measures it |
| 114 | +by recording kernel start and end timestamps from CUPTI activity records |
| 115 | +(``CONCURRENT_KERNEL``) and computing ``end - start`` per kernel launch. |
| 116 | + |
| 117 | +**Replay mode.** Neither kernel replay nor range replay is supported. CUPTI |
| 118 | +activity records capture one execution of each kernel in a single pass, so no |
| 119 | +replay mechanism is engaged and ``replay_mode`` is ignored. |
| 120 | + |
| 121 | +**Clock and cache control.** ``clock_control`` and ``cache_control`` are |
| 122 | +ignored. Clocks are not locked and caches are not flushed between runs, which |
| 123 | +may affect measurement stability. |
| 124 | + |
| 125 | +**Device synchronization.** The whole device is synchronized once after the |
| 126 | +profiling session, before the activity buffers are flushed, because a kernel's |
| 127 | +activity record is only written when the kernel completes. Work that the |
| 128 | +profiled function left running asynchronously is therefore waited for before |
| 129 | +profiling returns. |
0 commit comments