Implement stream-wide event reuse

This commit is contained in:
Andrzej Janik
2021-07-04 19:06:37 +02:00
parent ce25035051
commit 5b593ec185
3 changed files with 49 additions and 22 deletions

View File

@ -1123,7 +1123,7 @@ impl<'a> Event<'a> {
} }
pub fn host_synchronize(&self, timeout_ns: u64) -> Result<()> { pub fn host_synchronize(&self, timeout_ns: u64) -> Result<()> {
check!{ sys::zeEventHostSynchronize(self.as_ffi(), timeout_ns) }; check! { sys::zeEventHostSynchronize(self.as_ffi(), timeout_ns) };
Ok(()) Ok(())
} }
@ -1136,6 +1136,11 @@ impl<'a> Event<'a> {
} }
} }
pub fn host_reset(&self) -> Result<()> {
check! { sys::zeEventHostReset(self.as_ffi()) };
Ok(())
}
unsafe fn with_raw_slice<'x, T>( unsafe fn with_raw_slice<'x, T>(
events: &[&Event<'x>], events: &[&Event<'x>],
f: impl FnOnce(u32, *mut sys::ze_event_handle_t) -> T, f: impl FnOnce(u32, *mut sys::ze_event_handle_t) -> T,

View File

@ -284,15 +284,14 @@ impl GlobalState {
Self::lock_stream(stream, |stream_data| { Self::lock_stream(stream, |stream_data| {
let l0_dev = unsafe { (*(*stream_data.context).device).base }; let l0_dev = unsafe { (*(*stream_data.context).device).base };
let l0_ctx = unsafe { &mut (*(*stream_data.context).device).l0_context }; let l0_ctx = unsafe { &mut (*(*stream_data.context).device).l0_context };
let event_pool = unsafe { &mut (*(*stream_data.context).device).event_pool };
let cmd_list = unsafe { transmute_lifetime(&stream_data.cmd_list) }; let cmd_list = unsafe { transmute_lifetime(&stream_data.cmd_list) };
stream_data // TODO: make new_marker drop-safe
.drop_finished_events(&mut |(_, marker)| event_pool.mark_as_free(marker))?; let (new_event, new_marker) = stream_data.get_event(l0_dev, l0_ctx)?;
stream_data.try_reuse_finished_events()?;
let prev_event = stream_data.get_last_event(); let prev_event = stream_data.get_last_event();
let prev_event_array = prev_event.map(|e| [e]); let prev_event_array = prev_event.map(|e| [e]);
let empty = []; let empty = [];
let prev_event_slice = prev_event_array.as_ref().map_or(&empty[..], |arr| &arr[..]); let prev_event_slice = prev_event_array.as_ref().map_or(&empty[..], |arr| &arr[..]);
let (new_event, new_marker) = event_pool.get(l0_dev, l0_ctx)?;
f(cmd_list, &new_event, prev_event_slice)?; f(cmd_list, &new_event, prev_event_slice)?;
stream_data.push_event((new_event, new_marker)); stream_data.push_event((new_event, new_marker));
Ok(()) Ok(())

View File

@ -35,7 +35,9 @@ pub struct StreamData {
pub context: *mut ContextData, pub context: *mut ContextData,
// Immediate CommandList // Immediate CommandList
pub cmd_list: l0::CommandList<'static>, pub cmd_list: l0::CommandList<'static>,
pub prev_events: VecDeque<(l0::Event<'static>, u64)>, pub busy_events: VecDeque<(l0::Event<'static>, u64)>,
// This could be a Vec, but I'd rather reuse earliest enqueued event not the one recently enqueued
pub free_events: VecDeque<(l0::Event<'static>, u64)>,
} }
impl StreamData { impl StreamData {
@ -46,7 +48,8 @@ impl StreamData {
Ok(StreamData { Ok(StreamData {
context: ptr::null_mut(), context: ptr::null_mut(),
cmd_list: l0::CommandList::new_immediate(ctx, device)?, cmd_list: l0::CommandList::new_immediate(ctx, device)?,
prev_events: VecDeque::new(), busy_events: VecDeque::new(),
free_events: VecDeque::new(),
}) })
} }
pub fn new(ctx: &mut ContextData) -> Result<Self, CUresult> { pub fn new(ctx: &mut ContextData) -> Result<Self, CUresult> {
@ -55,20 +58,20 @@ impl StreamData {
Ok(StreamData { Ok(StreamData {
context: ctx as *mut _, context: ctx as *mut _,
cmd_list: l0::CommandList::new_immediate(l0_ctx, device)?, cmd_list: l0::CommandList::new_immediate(l0_ctx, device)?,
prev_events: VecDeque::new(), busy_events: VecDeque::new(),
free_events: VecDeque::new(),
}) })
} }
pub fn drop_finished_events( pub fn try_reuse_finished_events(&mut self) -> l0::Result<()> {
&mut self,
f: &mut impl FnMut((l0::Event<'static>, u64)),
) -> l0::Result<()> {
loop { loop {
match self.prev_events.get(0) { match self.busy_events.get(0) {
None => return Ok(()), None => return Ok(()),
Some((ev, _)) => { Some((ev, _)) => {
if ev.is_ready()? { if ev.is_ready()? {
f(self.prev_events.pop_front().unwrap()); let (ev, marker) = self.busy_events.pop_front().unwrap();
ev.host_reset()?;
self.free_events.push_back((ev, marker));
} else { } else {
return Ok(()); return Ok(());
} }
@ -77,28 +80,44 @@ impl StreamData {
} }
} }
pub fn drop_all_events(&mut self, f: &mut impl FnMut((l0::Event<'static>, u64))) { pub fn reuse_all_finished_events(&mut self) -> l0::Result<()> {
for x in self.prev_events.drain(..) { self.free_events.reserve(self.busy_events.len());
f(x); for (ev, marker) in self.busy_events.drain(..) {
ev.host_reset()?;
self.free_events.push_back((ev, marker));
} }
Ok(())
} }
pub fn get_last_event(&self) -> Option<&l0::Event<'static>> { pub fn get_last_event(&self) -> Option<&l0::Event<'static>> {
self.prev_events.iter().next_back().map(|(ev, _)| ev) self.busy_events.iter().next_back().map(|(ev, _)| ev)
} }
pub fn push_event(&mut self, ev: (l0::Event<'static>, u64)) { pub fn push_event(&mut self, ev: (l0::Event<'static>, u64)) {
self.prev_events.push_back(ev); self.busy_events.push_back(ev);
} }
pub fn synchronize(&mut self) -> l0::Result<()> { pub fn synchronize(&mut self) -> l0::Result<()> {
if let Some((ev, _)) = self.prev_events.back() { if let Some((ev, _)) = self.busy_events.back() {
ev.host_synchronize(u64::MAX)?; ev.host_synchronize(u64::MAX)?;
} }
let event_pool = unsafe { &mut (*(*self.context).device).event_pool }; self.reuse_all_finished_events()?;
self.drop_all_events(&mut |(_, marker)| event_pool.mark_as_free(marker));
Ok(()) Ok(())
} }
pub fn get_event(
&mut self,
l0_dev: l0::Device,
l0_ctx: &'static l0::Context,
) -> l0::Result<(l0::Event<'static>, u64)> {
self.free_events
.pop_front()
.map(|x| Ok(x))
.unwrap_or_else(|| {
let event_pool = unsafe { &mut (*(*self.context).device).event_pool };
event_pool.get(l0_dev, l0_ctx)
})
}
} }
impl Drop for StreamData { impl Drop for StreamData {
@ -106,6 +125,10 @@ impl Drop for StreamData {
if self.context == ptr::null_mut() { if self.context == ptr::null_mut() {
return; return;
} }
for (_, marker) in self.busy_events.iter().chain(self.free_events.iter()) {
let event_pool = unsafe { &mut (*(*self.context).device).event_pool };
event_pool.mark_as_free(*marker);
}
unsafe { (&mut *self.context).streams.remove(&(&mut *self as *mut _)) }; unsafe { (&mut *self.context).streams.remove(&(&mut *self as *mut _)) };
} }
} }