use crate::error::{DriverError, IntoResult};
use crate::simt::context::CudaContext;
use crate::simt::stream::CudaStream;
use std::mem::MaybeUninit;
use std::sync::Arc;
#[derive(Debug)]
pub struct CudaEvent {
pub(crate) cu_event: cuda_bindings::CUevent,
pub(crate) ctx: Arc<CudaContext>,
}
unsafe impl Send for CudaEvent {}
unsafe impl Sync for CudaEvent {}
impl Drop for CudaEvent {
fn drop(&mut self) {
self.ctx.record_err(self.ctx.bind_to_thread());
self.ctx
.record_err(unsafe { cuda_bindings::cuEventDestroy_v2(self.cu_event).result() });
}
}
impl CudaContext {
pub fn new_event(
self: &Arc<Self>,
flags: Option<cuda_bindings::CUevent_flags>,
) -> Result<CudaEvent, DriverError> {
let flags = flags.unwrap_or(cuda_bindings::CUevent_flags_enum_CU_EVENT_DISABLE_TIMING);
self.bind_to_thread()?;
let mut cu_event = MaybeUninit::uninit();
let cu_event = unsafe {
cuda_bindings::cuEventCreate(cu_event.as_mut_ptr(), flags).result()?;
cu_event.assume_init()
};
Ok(CudaEvent {
cu_event,
ctx: self.clone(),
})
}
}
impl CudaEvent {
pub fn cu_event(&self) -> cuda_bindings::CUevent {
self.cu_event
}
pub fn context(&self) -> &Arc<CudaContext> {
&self.ctx
}
pub fn record(&self, stream: &CudaStream) -> Result<(), DriverError> {
self.ctx.bind_to_thread()?;
unsafe { cuda_bindings::cuEventRecord(self.cu_event, stream.cu_stream()).result() }
}
pub fn synchronize(&self) -> Result<(), DriverError> {
self.ctx.bind_to_thread()?;
unsafe { cuda_bindings::cuEventSynchronize(self.cu_event).result() }
}
pub fn query(&self) -> Result<bool, DriverError> {
self.ctx.bind_to_thread()?;
match unsafe { cuda_bindings::cuEventQuery(self.cu_event) } {
cuda_bindings::cudaError_enum_CUDA_SUCCESS => Ok(true),
cuda_bindings::cudaError_enum_CUDA_ERROR_NOT_READY => Ok(false),
err => Err(DriverError(err)),
}
}
pub fn elapsed_ms(&self, end: &Self) -> Result<f32, DriverError> {
self.synchronize()?;
end.synchronize()?;
let mut ms: f32 = 0.0;
unsafe {
cuda_bindings::cu_event_elapsed_time(&mut ms as *mut _, self.cu_event, end.cu_event)
.result()?;
}
Ok(ms)
}
}