#[cfg(test)]
use crate::driver::CuStream;
use crate::{context::CudaContext, driver::CuEvent, error::CudaError};
#[cfg(test)]
#[derive(Debug)]
pub(crate) struct CudaStream {
pub(crate) context: CudaContext,
pub(crate) stream: CuStream,
}
#[cfg(test)]
impl Drop for CudaStream {
fn drop(&mut self) {
if !self.stream.is_null() {
let destroy_result = self.context.inner.with_current_stateful_operation(|| {
self.context
.inner
.driver
.check("cuStreamDestroy_v2", unsafe {
(self.context.inner.driver.cu_stream_destroy)(self.stream)
})
});
if destroy_result.is_err() {
std::mem::forget(self.context.clone());
}
}
}
}
#[cfg(test)]
unsafe impl Send for CudaStream {}
#[derive(Debug)]
pub(crate) struct CudaEvent {
pub(crate) context: CudaContext,
pub(crate) event: CuEvent,
}
impl CudaEvent {
#[cfg(test)]
pub(crate) fn record(&self, stream: &CudaStream) -> Result<(), CudaError> {
if !self.context.is_same_context(&stream.context) {
return Err(CudaError::InvalidArgument {
message: "CUDA event and stream must belong to the same context".to_string(),
});
}
self.context.inner.with_current_resource_operation(|| {
self.context.inner.driver.check("cuEventRecord", unsafe {
(self.context.inner.driver.cu_event_record)(self.event, stream.stream)
})
})
}
pub(crate) fn record_default_stream(&self) -> Result<(), CudaError> {
self.context.inner.with_current_resource_operation(|| {
self.context.inner.driver.check("cuEventRecord", unsafe {
(self.context.inner.driver.cu_event_record)(self.event, std::ptr::null_mut())
})
})
}
pub(crate) fn synchronize(&self) -> Result<(), CudaError> {
self.context.inner.with_current_resource_operation(|| {
self.context
.inner
.driver
.check("cuEventSynchronize", unsafe {
(self.context.inner.driver.cu_event_synchronize)(self.event)
})
})
}
pub(crate) fn elapsed_time_us(start: &Self, end: &Self) -> Result<f32, CudaError> {
if !start.context.is_same_context(&end.context) {
return Err(CudaError::InvalidArgument {
message: "CUDA timing events must belong to the same context".to_string(),
});
}
let mut millis = 0.0f32;
end.context.inner.with_current_resource_operation(|| {
let status = unsafe {
(end.context.inner.driver.cu_event_elapsed_time)(
&raw mut millis,
start.event,
end.event,
)
};
end.context.inner.driver.check("cuEventElapsedTime", status)
})?;
Ok(millis * 1000.0)
}
}
impl Drop for CudaEvent {
fn drop(&mut self) {
if !self.event.is_null() {
let destroy_result = self.context.inner.with_current_stateful_operation(|| {
self.context
.inner
.driver
.check("cuEventDestroy_v2", unsafe {
(self.context.inner.driver.cu_event_destroy)(self.event)
})
});
if destroy_result.is_err() {
std::mem::forget(self.context.clone());
}
}
}
}
unsafe impl Send for CudaEvent {}