Skip to main content

baracuda_runtime/
lib.rs

1//! Safe Rust wrappers for the CUDA Runtime API.
2//!
3//! The Runtime API is "higher level" than the Driver API: contexts are
4//! implicit (each device has a primary context the runtime uses
5//! automatically), kernels are typically linked at build time by `nvcc`,
6//! and most operations dispatch to the current thread's current device.
7//! baracuda-runtime mirrors the Driver-side types where it makes sense
8//! ([`Device`], [`Stream`], [`Event`], [`DeviceBuffer`]) and uses the
9//! CUDA 12.0+ library API ([`Library`], [`Kernel`]) for loading PTX at
10//! runtime — the Driver-API equivalent of `Module::load_ptx` +
11//! `Module::get_function`.
12//!
13//! # Driver ↔ Runtime interop
14//!
15//! `CUstream` and `cudaStream_t` are the same C type. With the
16//! `driver-interop` feature, `Stream::as_raw_driver()` and
17//! `Event::as_raw_driver()` return views usable by `baracuda-driver`
18//! APIs. See [`interop`].
19//!
20//! # Examples
21//!
22//! **Device query** — discover the visible GPUs and inspect compute
23//! capability + SM count.
24//!
25//! ```no_run
26//! use baracuda_runtime::Device;
27//!
28//! # fn demo() -> Result<(), Box<dyn std::error::Error>> {
29//! let count = Device::count()?;
30//! for d in Device::all()? {
31//!     let (major, minor) = d.compute_capability()?;
32//!     println!("device {}: cc {major}.{minor}, {} SMs", d.ordinal(),
33//!         d.multiprocessor_count()?);
34//! }
35//! # let _ = count; Ok(()) }
36//! ```
37//!
38//! **Async memory copy** — overlap H2D upload with later kernel launches
39//! by issuing on a non-blocking [`Stream`].
40//!
41//! ```no_run
42//! use baracuda_runtime::{Device, DeviceBuffer, Stream};
43//!
44//! # fn demo() -> Result<(), Box<dyn std::error::Error>> {
45//! Device::from_ordinal(0).set_current()?;
46//! let stream = Stream::non_blocking()?;
47//!
48//! let host: Vec<f32> = (0..4096).map(|i| i as f32).collect();
49//! let device: DeviceBuffer<f32> = DeviceBuffer::new(host.len())?;
50//! device.copy_from_host_async(&host, &stream)?;
51//!
52//! let mut back = vec![0.0f32; host.len()];
53//! device.copy_to_host_async(&mut back, &stream)?;
54//! stream.synchronize()?;
55//! assert_eq!(host, back);
56//! # Ok(()) }
57//! ```
58//!
59//! **Event timing** — measure the elapsed device time between two
60//! [`Event::record`] calls.
61//!
62//! ```no_run
63//! use baracuda_runtime::{Device, DeviceBuffer, Event, Stream};
64//!
65//! # fn demo() -> Result<(), Box<dyn std::error::Error>> {
66//! Device::from_ordinal(0).set_current()?;
67//! let stream = Stream::new()?;
68//! let start = Event::new()?;
69//! let end   = Event::new()?;
70//!
71//! // Record START -> issue some work -> record END.
72//! start.record(&stream)?;
73//! let buf: DeviceBuffer<f32> = DeviceBuffer::zeros(1 << 20)?;
74//! end.record(&stream)?;
75//! end.synchronize()?;
76//!
77//! let ms = Event::elapsed_time_ms(&start, &end)?;
78//! println!("device-side elapsed: {ms} ms");
79//! # let _ = buf; Ok(()) }
80//! ```
81
82#![warn(missing_debug_implementations)]
83
84pub mod array;
85pub mod device;
86pub mod driver_entry;
87pub mod error;
88pub mod event;
89pub mod external;
90pub mod graph;
91pub mod graphics;
92pub mod green;
93pub mod init;
94pub mod ipc;
95pub mod launch;
96pub mod launch_attr;
97pub mod memcpy2d;
98pub mod memcpy3d;
99pub mod memory;
100pub mod mempool;
101pub mod module;
102pub mod multicast;
103pub mod profiler;
104pub mod query;
105pub mod stream;
106pub mod user_object;
107pub mod vmm;
108
109#[cfg(feature = "driver-interop")]
110pub mod interop;
111
112pub use device::Device;
113pub use error::{Error, Result};
114pub use event::Event;
115pub use graph::{CaptureMode, Graph, GraphExec, GraphNode, UpdateResult};
116pub use init::{
117    device_synchronize, driver_version, get_device_flags, last_error, peek_last_error,
118    runtime_version, set_device_flags,
119};
120pub use launch::{Dim3, LaunchBuilder};
121pub use memory::DeviceBuffer;
122pub use module::{Kernel, Library};
123pub use stream::Stream;