use std::collections::HashMap;
use xlog_core::XlogError;
use xlog_cuda::{CudaBuffer, CudaKernelProvider};
pub fn read_device_row_count(
provider: &CudaKernelProvider,
buffer: &CudaBuffer,
) -> Result<usize, XlogError> {
provider.device_row_count(buffer)
}
pub struct IlpRegistry {
masks: HashMap<String, IlpMask>,
}
#[allow(clippy::large_enum_variant)]
pub enum IlpMask {
Dense {
hard: CudaBuffer,
soft: CudaBuffer,
schema_size: usize,
},
Sparse {
active_entries: Vec<(u32, u32, u32)>,
schema_size: usize,
},
SparseDevice {
candidate_order: Vec<(u32, u32, u32)>,
active_flags: CudaBuffer,
selected_count: usize,
schema_size: usize,
},
}
impl IlpMask {
pub fn schema_size(&self) -> usize {
match self {
IlpMask::Dense { schema_size, .. } => *schema_size,
IlpMask::Sparse { schema_size, .. } => *schema_size,
IlpMask::SparseDevice { schema_size, .. } => *schema_size,
}
}
}
pub struct IlpTaggedResult {
pub entries: Vec<IlpTagEntry>,
}
pub struct IlpTagEntry {
pub i: u32,
pub j: u32,
pub k: u32,
pub num_rows: u32,
pub buffer: Option<CudaBuffer>,
}
impl IlpRegistry {
pub fn new() -> Self {
Self {
masks: HashMap::new(),
}
}
pub fn clear(&mut self) {
self.masks.clear();
}
pub fn insert_mask(
&mut self,
name: String,
hard: CudaBuffer,
soft: CudaBuffer,
schema_size: usize,
) {
self.masks.insert(
name,
IlpMask::Dense {
hard,
soft,
schema_size,
},
);
}
pub fn insert_mask_from_sparse(
&mut self,
name: String,
schema_size: usize,
active_ijk: &[(u32, u32, u32)],
active_soft: &[f32],
budget: usize,
) -> Result<(), XlogError> {
if active_ijk.len() != active_soft.len() {
return Err(XlogError::Execution(format!(
"active_ijk length {} != active_soft length {}",
active_ijk.len(),
active_soft.len()
)));
}
let mut ranked: Vec<(usize, f32)> = active_soft.iter().copied().enumerate().collect();
ranked.retain(|(_, soft)| *soft > 0.0);
ranked.sort_by(|a, b| {
b.1.partial_cmp(&a.1)
.unwrap_or(std::cmp::Ordering::Equal)
.then(a.0.cmp(&b.0))
});
ranked.truncate(budget.min(ranked.len()));
let entries: Vec<(u32, u32, u32)> =
ranked.iter().map(|&(idx, _)| active_ijk[idx]).collect();
self.masks.insert(
name,
IlpMask::Sparse {
active_entries: entries,
schema_size,
},
);
Ok(())
}
pub fn insert_selected_mask(
&mut self,
name: String,
schema_size: usize,
active_entries: &[(u32, u32, u32)],
) {
self.masks.insert(
name,
IlpMask::Sparse {
active_entries: active_entries.to_vec(),
schema_size,
},
);
}
pub fn insert_selected_mask_device(
&mut self,
name: String,
schema_size: usize,
candidate_order: Vec<(u32, u32, u32)>,
active_flags: CudaBuffer,
selected_count: usize,
) {
self.masks.insert(
name,
IlpMask::SparseDevice {
candidate_order,
active_flags,
selected_count,
schema_size,
},
);
}
pub fn get_mask(&self, name: &str) -> Option<&IlpMask> {
self.masks.get(name)
}
pub fn has_sparse_device_mask(&self) -> bool {
self.masks
.values()
.any(|mask| matches!(mask, IlpMask::SparseDevice { .. }))
}
}
impl Default for IlpRegistry {
fn default() -> Self {
Self::new()
}
}