1use std::collections::HashMap;
4use xlog_core::XlogError;
5use xlog_cuda::{CudaBuffer, CudaKernelProvider};
6
7pub fn read_device_row_count(
9 provider: &CudaKernelProvider,
10 buffer: &CudaBuffer,
11) -> Result<usize, XlogError> {
12 provider.device_row_count(buffer)
13}
14
15pub struct IlpRegistry {
17 masks: HashMap<String, IlpMask>,
18}
19
20pub enum IlpMask {
22 Dense {
24 hard: CudaBuffer,
26 soft: CudaBuffer,
28 schema_size: usize,
30 },
31 Sparse {
33 active_entries: Vec<(u32, u32, u32)>,
35 schema_size: usize,
37 },
38 SparseDevice {
40 candidate_order: Vec<(u32, u32, u32)>,
42 active_flags: CudaBuffer,
44 selected_count: usize,
46 schema_size: usize,
48 },
49}
50
51impl IlpMask {
52 pub fn schema_size(&self) -> usize {
54 match self {
55 IlpMask::Dense { schema_size, .. } => *schema_size,
56 IlpMask::Sparse { schema_size, .. } => *schema_size,
57 IlpMask::SparseDevice { schema_size, .. } => *schema_size,
58 }
59 }
60}
61
62pub struct IlpTaggedResult {
65 pub entries: Vec<IlpTagEntry>,
67}
68
69pub struct IlpTagEntry {
72 pub i: u32,
74 pub j: u32,
76 pub k: u32,
78 pub num_rows: u32,
80 pub buffer: Option<CudaBuffer>,
82}
83
84impl IlpRegistry {
85 pub fn new() -> Self {
87 Self {
88 masks: HashMap::new(),
89 }
90 }
91
92 pub fn clear(&mut self) {
94 self.masks.clear();
95 }
96
97 pub fn insert_mask(
99 &mut self,
100 name: String,
101 hard: CudaBuffer,
102 soft: CudaBuffer,
103 schema_size: usize,
104 ) {
105 self.masks.insert(
106 name,
107 IlpMask::Dense {
108 hard,
109 soft,
110 schema_size,
111 },
112 );
113 }
114
115 pub fn insert_mask_from_sparse(
120 &mut self,
121 name: String,
122 schema_size: usize,
123 active_ijk: &[(u32, u32, u32)],
124 active_soft: &[f32],
125 budget: usize,
126 ) -> Result<(), XlogError> {
127 if active_ijk.len() != active_soft.len() {
128 return Err(XlogError::Execution(format!(
129 "active_ijk length {} != active_soft length {}",
130 active_ijk.len(),
131 active_soft.len()
132 )));
133 }
134
135 let mut ranked: Vec<(usize, f32)> = active_soft.iter().copied().enumerate().collect();
138 ranked.retain(|(_, soft)| *soft > 0.0);
139 ranked.sort_by(|a, b| {
140 b.1.partial_cmp(&a.1)
141 .unwrap_or(std::cmp::Ordering::Equal)
142 .then(a.0.cmp(&b.0))
143 });
144 ranked.truncate(budget.min(ranked.len()));
145
146 let entries: Vec<(u32, u32, u32)> =
147 ranked.iter().map(|&(idx, _)| active_ijk[idx]).collect();
148
149 self.masks.insert(
150 name,
151 IlpMask::Sparse {
152 active_entries: entries,
153 schema_size,
154 },
155 );
156 Ok(())
157 }
158
159 pub fn insert_selected_mask(
161 &mut self,
162 name: String,
163 schema_size: usize,
164 active_entries: &[(u32, u32, u32)],
165 ) {
166 self.masks.insert(
167 name,
168 IlpMask::Sparse {
169 active_entries: active_entries.to_vec(),
170 schema_size,
171 },
172 );
173 }
174
175 pub fn insert_selected_mask_device(
177 &mut self,
178 name: String,
179 schema_size: usize,
180 candidate_order: Vec<(u32, u32, u32)>,
181 active_flags: CudaBuffer,
182 selected_count: usize,
183 ) {
184 self.masks.insert(
185 name,
186 IlpMask::SparseDevice {
187 candidate_order,
188 active_flags,
189 selected_count,
190 schema_size,
191 },
192 );
193 }
194
195 pub fn get_mask(&self, name: &str) -> Option<&IlpMask> {
197 self.masks.get(name)
198 }
199
200 pub fn has_sparse_device_mask(&self) -> bool {
202 self.masks
203 .values()
204 .any(|mask| matches!(mask, IlpMask::SparseDevice { .. }))
205 }
206}
207
208impl Default for IlpRegistry {
209 fn default() -> Self {
210 Self::new()
211 }
212}