vyre_runtime/megakernel/execution/
types.rs1use crate::PipelineError;
2use vyre_driver::backend::{OutputBuffers, Resource};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct MegakernelDispatchStats {
7 pub input_bytes: u64,
9 pub output_bytes: u64,
11 pub readback_bytes: u64,
13 pub bytes_moved: u64,
15 pub device_allocation_bytes: u64,
17 pub device_allocation_events: u32,
19 pub latency_ns: u64,
21 pub output_buffers: u32,
23 pub resident_resource_rows: u32,
25 pub resident_resource_handles: u32,
27 pub kernel_launches: u32,
29 pub sync_points: u32,
31 pub recovered_after_device_loss: bool,
34}
35
36impl MegakernelDispatchStats {
37 #[must_use]
39 pub fn output_bytes_per_second(&self) -> u64 {
40 bytes_per_second_or_panic(self.output_bytes, self.latency_ns, "output bytes")
41 }
42
43 #[must_use]
45 pub fn readback_bytes_per_second(&self) -> u64 {
46 bytes_per_second_or_panic(self.readback_bytes, self.latency_ns, "readback bytes")
47 }
48
49 #[must_use]
51 pub fn bytes_moved_per_second(&self) -> u64 {
52 bytes_per_second_or_panic(self.bytes_moved, self.latency_ns, "moved bytes")
53 }
54
55 #[must_use]
57 pub fn device_allocation_bytes_per_second(&self) -> u64 {
58 bytes_per_second_or_panic(
59 self.device_allocation_bytes,
60 self.latency_ns,
61 "device allocation bytes",
62 )
63 }
64}
65
66fn bytes_per_second_or_panic(bytes: u64, latency_ns: u64, _label: &'static str) -> u64 {
67 if latency_ns == 0 {
68 return 0;
69 }
70 let scaled = (bytes as u128) * 1_000_000_000u128;
71 let rate = scaled / u128::from(latency_ns);
72 rate.min(u128::from(u64::MAX)) as u64
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct MegakernelDispatchOutput {
78 pub buffers: Vec<Vec<u8>>,
80 pub stats: MegakernelDispatchStats,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
87pub struct MegakernelBatchDispatchOutput {
88 pub batches: Vec<Vec<Vec<u8>>>,
90 pub stats: MegakernelDispatchStats,
92}
93
94#[derive(Debug, Default)]
101pub struct MegakernelResidentBatchScratch {
102 pub(super) resources: Vec<[Resource; 4]>,
103 pub(super) batches: Vec<OutputBuffers>,
104 pub(super) active_batches: usize,
105}
106
107impl MegakernelResidentBatchScratch {
108 #[must_use]
110 pub fn new() -> Self {
111 Self::default()
112 }
113
114 pub fn with_capacity(
122 batch_count: usize,
123 output_slots_per_batch: usize,
124 ) -> Result<Self, PipelineError> {
125 let mut resources = Vec::new();
126 vyre_foundation::allocation::try_reserve_vec_to_capacity(&mut resources, batch_count)
127 .map_err(|error| {
128 PipelineError::Backend(format!(
129 "megakernel resident batch scratch could not reserve {batch_count} resource row(s): {error}. Fix: split persistent-handle batches before dispatch."
130 ))
131 })?;
132 let mut batches = Vec::new();
133 vyre_foundation::allocation::try_reserve_vec_to_capacity(&mut batches, batch_count)
134 .map_err(|error| {
135 PipelineError::Backend(format!(
136 "megakernel resident batch scratch could not reserve {batch_count} batch row(s): {error}. Fix: split persistent-handle batches before dispatch."
137 ))
138 })?;
139 for _ in 0..batch_count {
140 let mut outputs = Vec::new();
141 vyre_foundation::allocation::try_reserve_vec_to_capacity(
142 &mut outputs,
143 output_slots_per_batch,
144 )
145 .map_err(|error| {
146 PipelineError::Backend(format!(
147 "megakernel resident batch scratch could not reserve {output_slots_per_batch} output slot(s): {error}. Fix: reduce resident output fanout or split persistent-handle batches."
148 ))
149 })?;
150 outputs.resize_with(output_slots_per_batch, Vec::new);
151 batches.push(outputs);
152 }
153 Ok(Self {
154 resources,
155 batches,
156 active_batches: 0,
157 })
158 }
159
160 #[must_use]
162 pub fn batches(&self) -> &[OutputBuffers] {
163 &self.batches[..self.active_batches.min(self.batches.len())]
164 }
165
166 pub fn batches_mut(&mut self) -> &mut Vec<OutputBuffers> {
169 &mut self.batches
170 }
171
172 pub fn clear(&mut self) {
174 self.resources.clear();
175 self.active_batches = 0;
176 for batch in &mut self.batches {
177 for output in batch {
178 output.clear();
179 }
180 }
181 }
182
183 #[must_use]
185 pub fn resource_capacity(&self) -> usize {
186 self.resources.capacity()
187 }
188
189 #[must_use]
191 pub fn batch_capacity(&self) -> usize {
192 self.batches.capacity()
193 }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202pub struct MegakernelResidentHandles {
203 pub control: u64,
205 pub ring: u64,
207 pub debug_log: u64,
209 pub io_queue: u64,
211}
212
213impl MegakernelResidentHandles {
214 pub const ABI_RESOURCE_COUNT: usize = 4;
216
217 #[must_use]
219 pub const fn new(control: u64, ring: u64, debug_log: u64, io_queue: u64) -> Self {
220 Self {
221 control,
222 ring,
223 debug_log,
224 io_queue,
225 }
226 }
227
228 pub(super) fn resources(self) -> [Resource; Self::ABI_RESOURCE_COUNT] {
229 [
230 Resource::Resident(self.control),
231 Resource::Resident(self.ring),
232 Resource::Resident(self.debug_log),
233 Resource::Resident(self.io_queue),
234 ]
235 }
236}