vyre_runtime/megakernel/planner/
sizing.rs1use vyre_driver::backend::BackendError;
2use vyre_foundation::execution_plan::SchedulingPolicy;
3
4use super::{ResidentGridLimits, ResidentGridPlan, ResidentGridRequest, ResidentLaunchGeometry};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub struct ResidentSizingPolicy {
12 scheduling: SchedulingPolicy,
13}
14
15impl Default for ResidentSizingPolicy {
16 fn default() -> Self {
17 Self::standard()
18 }
19}
20
21impl ResidentSizingPolicy {
22 #[must_use]
24 pub const fn standard() -> Self {
25 Self {
26 scheduling: SchedulingPolicy::standard(),
27 }
28 }
29
30 #[must_use]
32 pub const fn from_scheduling(scheduling: SchedulingPolicy) -> Self {
33 Self { scheduling }
34 }
35
36 #[must_use]
38 pub const fn default_worker_count(&self) -> u32 {
39 self.scheduling.default_worker_count()
40 }
41
42 #[must_use]
44 pub const fn worker_workgroup_size(&self, worker_count: u32, max_workgroup_size_x: u32) -> u32 {
45 self.scheduling
46 .worker_workgroup_size(worker_count, max_workgroup_size_x)
47 }
48
49 #[must_use]
51 pub const fn padded_slot_count(&self, slot_count: u32, workgroup_size_x: u32) -> u32 {
52 self.scheduling
53 .padded_slot_count(slot_count, workgroup_size_x)
54 }
55
56 #[must_use]
58 pub const fn dispatch_grid_for(
59 &self,
60 worker_count: u32,
61 queue_len: u32,
62 max_workgroup_size_x: u32,
63 ) -> [u32; 3] {
64 self.scheduling
65 .dispatch_grid_for(worker_count, queue_len, max_workgroup_size_x)
66 }
67
68 #[must_use]
70 pub const fn default_worker_groups_from_limits(
71 &self,
72 max_compute_workgroups_per_dimension: u32,
73 max_compute_invocations_per_workgroup: u32,
74 ) -> u32 {
75 self.scheduling.default_worker_groups_from_limits(
76 max_compute_workgroups_per_dimension,
77 max_compute_invocations_per_workgroup,
78 )
79 }
80
81 pub fn calculate_optimal_grid(
87 &self,
88 request: ResidentGridRequest,
89 limits: ResidentGridLimits,
90 ) -> Result<ResidentGridPlan, BackendError> {
91 limits.validate()?;
92
93 let occupancy_worker_groups = self
94 .default_worker_groups_from_limits(
95 limits.max_compute_workgroups_per_dimension,
96 limits.max_compute_invocations_per_workgroup,
97 )
98 .min(limits.max_compute_workgroups_per_dimension);
99
100 let worker_groups = if request.requested_worker_groups == 0 {
101 occupancy_worker_groups
102 } else {
103 request
104 .requested_worker_groups
105 .min(limits.max_compute_workgroups_per_dimension)
106 }
107 .max(1);
108
109 let geometry = self.geometry_from_slots(
110 request.queue_len.max(1),
111 worker_groups,
112 limits.max_workgroup_size_x,
113 );
114
115 Ok(ResidentGridPlan {
116 geometry,
117 worker_groups,
118 })
119 }
120
121 #[must_use]
123 pub fn geometry_from_slots(
124 &self,
125 slot_count: u32,
126 worker_count: u32,
127 max_workgroup_size_x: u32,
128 ) -> ResidentLaunchGeometry {
129 let workgroup_size_x = self.worker_workgroup_size(worker_count, max_workgroup_size_x);
130 let slot_count = self.padded_slot_count(slot_count, workgroup_size_x);
131 let dispatch_grid = self.dispatch_grid_for(worker_count, slot_count, workgroup_size_x);
132 ResidentLaunchGeometry {
133 workgroup_size_x,
134 slot_count,
135 dispatch_grid,
136 }
137 }
138}