Skip to content

Commit 01374dc

Browse files
authored
Drop output parameter - replace with "verbosity" (#44)
Signed-off-by: Alok Joshi <aljoshi@nvidia.com>
1 parent 80f5b4d commit 01374dc

15 files changed

Lines changed: 178 additions & 129 deletions

‎nsight/__init__.py‎

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

66
from nsight import analyze
77
from nsight.annotation import annotate
8-
from nsight.utils import col_panel, row_panel
8+
from nsight.utils import VerbosityLevel, col_panel, row_panel
99

1010
__version__ = version("nsight-python")
1111

12-
__all__ = ["analyze", "annotate"]
12+
__all__ = ["analyze", "annotate", "VerbosityLevel"]

‎nsight/analyze.py‎

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import nsight.collection as collection
1818
import nsight.visualization as visualization
19+
from nsight.utils import VerbosityLevel
1920

2021

2122
# Overload 1: When used without parentheses: @kernel
@@ -39,7 +40,7 @@ def kernel(
3940
| None
4041
) = None,
4142
normalize_against: str | None = None,
42-
output: Literal["quiet", "progress", "verbose"] = "progress",
43+
verbosity: VerbosityLevel = VerbosityLevel.INFO,
4344
metrics: Sequence[str] = ["gpu__time_duration.sum"],
4445
ignore_kernel_list: Sequence[str] | None = None,
4546
clock_control: Literal["base", "none"] = "none",
@@ -68,7 +69,7 @@ def kernel(
6869
| None
6970
) = None,
7071
normalize_against: str | None = None,
71-
output: Literal["quiet", "progress", "verbose"] = "progress",
72+
verbosity: VerbosityLevel = VerbosityLevel.INFO,
7273
metrics: Sequence[str] = ["gpu__time_duration.sum"],
7374
ignore_kernel_list: Sequence[str] | None = None,
7475
clock_control: Literal["base", "none"] = "none",
@@ -219,11 +220,14 @@ def wrapped_function(*args, configs=None, **kwargs) -> ProfileResults
219220
thermal_timeout: Maximum wait time in seconds for GPU to cool down.
220221
Default: 180 seconds
221222
222-
output: Controls the verbosity level of the output.
223+
verbosity: Controls the verbosity level of the output. Selecting level N
224+
enables output at all levels with value <= N. Default: ``VerbosityLevel.INFO``.
223225
224-
- ``"quiet"``: Suppresses all output.
225-
- ``"progress"``: Shows a progress bar along with details about profiling and data extraction progress.
226-
- ``"verbose"``: Displays the progress bar, configuration-specific logs, and profiler logs.
226+
- ``VerbosityLevel.SILENT``: Suppresses all output.
227+
- ``VerbosityLevel.INFO``: Shows a progress bar, profiling completion messages,
228+
and report file paths.
229+
- ``VerbosityLevel.DEBUG``: Adds configuration-specific logs, the full NCU CLI
230+
command, and enables NCU verbose output.
227231
228232
output_prefix: When specified, all intermediate profiler files are created with this prefix.
229233
For example, if `output_prefix="/home/user/run1_"`, the profiler will generate:
@@ -291,12 +295,6 @@ def wrapped_function(*args, configs=None, **kwargs) -> ProfileResults
291295

292296
def _create_profiler() -> collection.core.NsightProfiler:
293297
"""Helper to create the profiler with the given settings."""
294-
if output not in ("quiet", "progress", "verbose"):
295-
raise ValueError("output must be 'quiet', 'progress' or 'verbose'")
296-
297-
output_progress = output == "progress" or output == "verbose"
298-
output_detailed = output == "verbose"
299-
300298
# Create the output paths needed for the ncu report, ncu logs and the CSVs
301299
prefix = output_prefix
302300
if "NSPY_NCU_PROFILE" not in os.environ:
@@ -311,8 +309,7 @@ def _create_profiler() -> collection.core.NsightProfiler:
311309
settings = collection.core.ProfileSettings(
312310
configs=configs,
313311
runs=runs,
314-
output_progress=output_progress,
315-
output_detailed=output_detailed,
312+
verbosity=verbosity,
316313
derive_metric=derive_metric,
317314
normalize_against=normalize_against,
318315
thermal_mode=thermal_mode,

‎nsight/collection/core.py‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import pandas as pd
1818

1919
from nsight import annotation, exceptions, thermovision, transformation, utils
20+
from nsight.utils import VerbosityLevel
2021

2122

2223
def _get_regular_params(
@@ -235,15 +236,14 @@ def run_profile_session(
235236
func: Callable[..., None],
236237
configs: List[Sequence[Any]],
237238
runs: int,
238-
output_progress: bool,
239-
output_detailed: bool,
239+
verbosity: VerbosityLevel,
240240
thermal_mode: Literal["auto", "manual", "off"],
241241
thermal_wait: int | None = None,
242242
thermal_cont: int | None = None,
243243
thermal_timeout: int | None = None,
244244
) -> None:
245245

246-
if output_progress:
246+
if verbosity >= VerbosityLevel.INFO:
247247
print("")
248248
print("")
249249

@@ -255,7 +255,7 @@ def run_profile_session(
255255
thermal_wait=thermal_wait,
256256
thermal_cont=thermal_cont,
257257
thermal_timeout=thermal_timeout,
258-
verbose=output_detailed,
258+
verbose=verbosity >= VerbosityLevel.DEBUG,
259259
)
260260
thermovision_initialized = thermal_controller.init()
261261
if not thermovision_initialized:
@@ -270,8 +270,8 @@ def run_profile_session(
270270
bar_length = 100
271271
progress_time: float = 0
272272

273-
# overwrite flag: we do not overwrite when output mode is detailed
274-
overwrite_output = not output_detailed
273+
# overwrite flag: we do not overwrite when output mode is debug
274+
overwrite_output = verbosity < VerbosityLevel.DEBUG
275275
show_return_type_warning = False
276276
config_lengths: list[int] = list()
277277

@@ -300,7 +300,7 @@ def run_profile_session(
300300

301301
curr_config += 1
302302

303-
if output_progress:
303+
if verbosity >= VerbosityLevel.INFO:
304304
utils.print_config(total_configs, curr_config, c, overwrite_output)
305305

306306
for i in range(runs):
@@ -328,7 +328,7 @@ def run_profile_session(
328328

329329
# Update time estimates every half second
330330
if time.time() - progress_time > 0.5:
331-
if output_progress:
331+
if verbosity >= VerbosityLevel.INFO:
332332
utils.print_progress_bar(
333333
total_runs,
334334
curr_run,
@@ -339,7 +339,7 @@ def run_profile_session(
339339
progress_time = time.time()
340340

341341
# Update progress bar at end so it shows 100%
342-
if output_progress:
342+
if verbosity >= VerbosityLevel.INFO:
343343
utils.print_progress_bar(
344344
total_runs,
345345
curr_run,
@@ -377,14 +377,10 @@ class ProfileSettings:
377377
runs: int
378378
"""Number of times each configuration should be executed."""
379379

380-
output_progress: bool
380+
verbosity: VerbosityLevel
381381
"""
382-
Will display a progress bar on stdout during profiling
383-
"""
384-
385-
output_detailed: bool
386-
"""
387-
Will display a progress bar, detailed output for each config along with the profiler logs
382+
Controls verbosity of output. SILENT suppresses all output, INFO shows progress bar,
383+
DEBUG shows progress bar plus per-config logs and profiler output.
388384
"""
389385

390386
derive_metric: (
@@ -596,7 +592,7 @@ def wrapper(
596592
raw_df,
597593
func,
598594
self.settings.normalize_against,
599-
self.settings.output_progress,
595+
self.settings.verbosity,
600596
)
601597

602598
# Save to CSV if enabled
@@ -617,7 +613,7 @@ def wrapper(
617613
index=False,
618614
)
619615

620-
if self.settings.output_progress:
616+
if self.settings.verbosity >= VerbosityLevel.INFO:
621617
print(
622618
f"[NSIGHT-PYTHON] Refer to {raw_csv_path} for the raw profiling data"
623619
)

‎nsight/collection/ncu.py‎

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from nsight import exceptions, extraction, utils
2222
from nsight.collection import core
2323
from nsight.exceptions import NCUErrorContext
24+
from nsight.utils import VerbosityLevel
2425

2526

2627
def get_signature(
@@ -40,7 +41,7 @@ def launch_ncu(
4041
cache_control: Literal["none", "all"],
4142
clock_control: Literal["none", "base"],
4243
replay_mode: Literal["kernel", "range"],
43-
verbose: bool,
44+
verbosity: VerbosityLevel,
4445
) -> str | None:
4546
"""
4647
Launch NVIDIA Nsight Compute to profile the current script with specified options.
@@ -51,7 +52,7 @@ def launch_ncu(
5152
cache_control: Select cache control option
5253
clock_control: Select clock control option
5354
replay_mode: Select replay mode option
54-
verbose: If False, log is written to a file (ncu_log.txt)
55+
verbosity: Controls output verbosity level.
5556
5657
Raises:
5758
NCUNotAvailableError: If NCU is not available on the system.
@@ -84,11 +85,16 @@ def launch_ncu(
8485
replay = f"--replay-mode {replay_mode}"
8586
log_path = os.path.splitext(report_path)[0] + ".log"
8687
log = f"--log-file {log_path}"
88+
8789
nvtx = f'--nvtx --nvtx-include "regex:{utils.NVTX_DOMAIN}@.+/"'
8890
metrics_str = ",".join(metrics)
91+
verbose_flag = "--verbose" if verbosity >= VerbosityLevel.DEBUG else ""
8992

9093
# Construct the ncu command
91-
ncu_command = f"""ncu {log} {cache} {clocks} {replay} {nvtx} --metrics {metrics_str} -f -o {report_path} {sys.executable} {script_path} {script_args}"""
94+
ncu_command = f"""ncu {log} {cache} {clocks} {replay} {nvtx} {verbose_flag} --metrics {metrics_str} -f -o {report_path} {sys.executable} {script_path} {script_args}"""
95+
96+
if verbosity >= VerbosityLevel.DEBUG:
97+
print(f"[NSIGHT-PYTHON] NCU command: {ncu_command}")
9298

9399
# Check if ncu is available on the system
94100
ncu_available = False
@@ -113,19 +119,16 @@ def launch_ncu(
113119
)
114120

115121
return log_path
116-
except subprocess.CalledProcessError as e:
122+
except subprocess.CalledProcessError:
117123
log_parser = utils.NCULogParser()
118124
error_logs = log_parser.get_logs(log_path, "ERROR")
119-
120-
# Create error context
121-
error_context = NCUErrorContext(
122-
errors=error_logs,
123-
log_file_path=log_path,
124-
metrics=metrics,
125-
)
126-
127-
error_message = utils.format_ncu_error_message(error_context)
128-
raise exceptions.ProfilerException(error_message) from None
125+
raise exceptions.ProfilerException(
126+
utils.format_ncu_error_message(
127+
NCUErrorContext(
128+
errors=error_logs, log_file_path=log_path, metrics=metrics
129+
)
130+
)
131+
) from None
129132
else:
130133
subprocess.run([sys.executable, script_path], env=env)
131134
raise exceptions.NCUNotAvailableError(
@@ -230,10 +233,10 @@ def collect(
230233
self.cache_control,
231234
self.clock_control,
232235
self.replay_mode,
233-
settings.output_detailed,
236+
settings.verbosity,
234237
)
235238

236-
if settings.output_progress:
239+
if settings.verbosity >= VerbosityLevel.INFO:
237240
print("[NSIGHT-PYTHON] Profiling completed successfully !")
238241
print(
239242
f"[NSIGHT-PYTHON] Refer to {report_path} for the NVIDIA Nsight Compute CLI report"
@@ -250,7 +253,7 @@ def collect(
250253
func,
251254
settings.derive_metric,
252255
self.ignore_kernel_list, # type: ignore[arg-type]
253-
settings.output_progress,
256+
settings.verbosity,
254257
self.combine_kernel_metrics,
255258
)
256259

@@ -264,7 +267,7 @@ def collect(
264267
if get_signature(func, configs_list) != sig:
265268
return None
266269

267-
if settings.output_progress:
270+
if settings.verbosity >= VerbosityLevel.INFO:
268271
utils.print_header(
269272
f"Profiling {func.__name__}",
270273
f"{len(configs_list)} configurations, {settings.runs} runs each",
@@ -274,8 +277,7 @@ def collect(
274277
func,
275278
configs_list,
276279
settings.runs,
277-
settings.output_progress,
278-
settings.output_detailed,
280+
settings.verbosity,
279281
settings.thermal_mode,
280282
settings.thermal_wait,
281283
settings.thermal_cont,

‎nsight/extraction.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
extract_ncu_action_data(action, metrics):
1212
Extracts performance data for a specific kernel action from an NVIDIA Nsight Compute report.
1313
14-
extract_df_from_report(report_path, metrics, configs, iterations, func, derive_metric, ignore_kernel_list, output_progress, combine_kernel_metrics=None):
14+
extract_df_from_report(report_path, metrics, configs, iterations, func, derive_metric, ignore_kernel_list, verbosity, combine_kernel_metrics=None):
1515
Processes the full NVIDIA Nsight Compute report and returns a pandas DataFrame containing performance metrics.
1616
"""
1717

@@ -27,7 +27,7 @@
2727
import pandas as pd
2828

2929
from nsight import exceptions, utils
30-
from nsight.utils import is_scalar
30+
from nsight.utils import VerbosityLevel, is_scalar
3131

3232
DerivedValue: TypeAlias = float | int | None
3333
DerivedValueWithUnit: TypeAlias = tuple[DerivedValue, str]
@@ -84,7 +84,7 @@ def extract_df_from_report(
8484
func: Callable[..., Any],
8585
derive_metric: Callable[..., Any] | None,
8686
ignore_kernel_list: List[str] | None,
87-
output_progress: bool,
87+
verbosity: VerbosityLevel,
8888
combine_kernel_metrics: Callable[[float, float], float] | None = None,
8989
) -> pd.DataFrame:
9090
"""
@@ -108,13 +108,13 @@ def extract_df_from_report(
108108
RuntimeError: If multiple kernels are detected per config without a combining function.
109109
exceptions.ProfilerException: If profiling results are missing or incomplete.
110110
"""
111-
if output_progress:
111+
if verbosity >= VerbosityLevel.INFO:
112112
print("[NSIGHT-PYTHON] Loading profiled data")
113113
try:
114114
report: ncu_report.IContext = ncu_report.load_report(report_path)
115115
except FileNotFoundError:
116116
raise exceptions.ProfilerException(
117-
"No NVIDIA Nsight Compute report found. Please run nsight-python with `@nsight.analyze.kernel(output='verbose')`"
117+
"No NVIDIA Nsight Compute report found. Please run nsight-python with `@nsight.analyze.kernel(verbosity=nsight.VerbosityLevel.DEBUG)`"
118118
"to identify the issue."
119119
)
120120

@@ -144,7 +144,7 @@ def extract_df_from_report(
144144
}
145145

146146
# Extract all profiling data
147-
if output_progress:
147+
if verbosity >= VerbosityLevel.INFO:
148148
print(f"Extracting profiling data")
149149
profiling_data: dict[str, list[utils.NCUActionData]] = {}
150150
for range_idx in range(report.num_ranges()):
@@ -171,7 +171,7 @@ def extract_df_from_report(
171171
profiling_data[annotation].append(data)
172172

173173
for annotation, annotation_data in profiling_data.items():
174-
if output_progress:
174+
if verbosity >= VerbosityLevel.INFO:
175175
print(f"Extracting {annotation} profiling data")
176176

177177
configs_repeated = [

‎nsight/transformation.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
import numpy as np
1616
import pandas as pd
1717

18+
from nsight.utils import VerbosityLevel
19+
1820

1921
def aggregate_data(
2022
df: pd.DataFrame,
2123
func: Callable[..., Any],
2224
normalize_against: str | None,
23-
output_progress: bool,
25+
verbosity: VerbosityLevel,
2426
) -> pd.DataFrame:
2527
"""
2628
Groups and aggregates profiling data by configuration and annotation.
@@ -29,12 +31,12 @@ def aggregate_data(
2931
df: The raw profiling results.
3032
func: Function representing kernel configuration parameters.
3133
normalize_against: Name of the annotation to normalize against.
32-
output_progress: Toggles the display of data processing logs
34+
verbosity: Controls display of data processing logs
3335
3436
Returns:
3537
Aggregated DataFrame and the (possibly normalized) metric name.
3638
"""
37-
if output_progress:
39+
if verbosity >= VerbosityLevel.INFO:
3840
print("[NSIGHT-PYTHON] Processing profiled data")
3941

4042
# Get the number of arguments in the signature of func (exclude *args/**kwargs)

0 commit comments

Comments
 (0)