oxicuda_driver/profiler.rs
1//! CUDA profiler control.
2//!
3//! Start and stop the CUDA profiler programmatically, or use the
4//! [`ProfilerGuard`] RAII type to scope profiling to a block.
5//!
6//! # Example
7//!
8//! ```rust,no_run
9//! # use oxicuda_driver::profiler;
10//! # fn main() -> Result<(), oxicuda_driver::CudaError> {
11//! {
12//! let _guard = profiler::ProfilerGuard::start()?;
13//! // ... GPU work to profile ...
14//! } // profiler stops here
15//! # Ok(())
16//! # }
17//! ```
18
19use crate::error::{CudaError, CudaResult};
20use crate::loader::try_driver;
21
22/// Starts the CUDA profiler (e.g. Nsight Systems / nvprof).
23///
24/// # Errors
25///
26/// Returns [`CudaError::NotSupported`] if the driver lacks `cuProfilerStart`,
27/// or another error on failure.
28pub fn profiler_start() -> CudaResult<()> {
29 let api = try_driver()?;
30 let f = api.cu_profiler_start.ok_or(CudaError::NotSupported)?;
31 crate::cuda_call!(f())
32}
33
34/// Stops the CUDA profiler.
35///
36/// # Errors
37///
38/// Returns [`CudaError::NotSupported`] if the driver lacks `cuProfilerStop`,
39/// or another error on failure.
40pub fn profiler_stop() -> CudaResult<()> {
41 let api = try_driver()?;
42 let f = api.cu_profiler_stop.ok_or(CudaError::NotSupported)?;
43 crate::cuda_call!(f())
44}
45
46/// RAII guard that starts the CUDA profiler on creation and stops it on drop.
47///
48/// This is useful for scoping profiling to a specific block of code.
49/// If the profiler fails to stop on drop, the error is silently ignored
50/// (since `Drop::drop` cannot return errors).
51pub struct ProfilerGuard {
52 _private: (),
53}
54
55impl ProfilerGuard {
56 /// Starts the CUDA profiler and returns a guard that will stop it on drop.
57 ///
58 /// # Errors
59 ///
60 /// Returns an error if `profiler_start()` fails.
61 pub fn start() -> CudaResult<Self> {
62 profiler_start()?;
63 Ok(Self { _private: () })
64 }
65}
66
67impl Drop for ProfilerGuard {
68 fn drop(&mut self) {
69 // Best-effort stop; we cannot propagate errors from Drop.
70 let _ = profiler_stop();
71 }
72}
73
74// ---------------------------------------------------------------------------
75// Tests
76// ---------------------------------------------------------------------------
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn profiler_start_returns_error_without_gpu() {
84 let result = profiler_start();
85 // On macOS or without a GPU driver, this should fail gracefully.
86 let _ = result;
87 }
88
89 #[test]
90 fn profiler_stop_returns_error_without_gpu() {
91 let result = profiler_stop();
92 let _ = result;
93 }
94
95 #[test]
96 fn profiler_guard_does_not_panic_without_gpu() {
97 // start() will fail, so the guard should not be created,
98 // and no panic should occur.
99 let result = ProfilerGuard::start();
100 let _ = result;
101 }
102}