runmat_execution/placement/
candidate.rs1use runmat_types::{RegionGuardId, RegionId};
2use serde::{Deserialize, Serialize};
3
4use super::ExecutionCostEstimate;
5
6#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum ExecutionCandidateKind {
9 SharedRuntime,
10 GenericNativeCpu,
11 SpecializedNativeCpu,
12 VectorizedNativeCpu,
13 CpuLibrary,
14 ProviderOperation,
15 ProviderLibrary,
16 ProviderGraph,
17 ProviderFusion,
18}
19
20impl ExecutionCandidateKind {
21 pub const fn is_provider(self) -> bool {
22 matches!(
23 self,
24 Self::ProviderOperation
25 | Self::ProviderLibrary
26 | Self::ProviderGraph
27 | Self::ProviderFusion
28 )
29 }
30}
31
32#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
33#[serde(rename_all = "snake_case", tag = "kind")]
34pub enum CandidateExecutionLocation {
35 Host,
36 Provider { device_id: u32 },
37}
38
39#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
40#[serde(rename_all = "snake_case")]
41pub enum CandidatePreparationState {
42 Ready,
43 Warm,
44 Cold,
45 Preparing,
46}
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "snake_case", tag = "kind")]
50pub enum CandidateOutputResidency {
51 Host,
52 Provider { device_id: u32 },
53 Mirrored { device_id: u32 },
54 Unknown,
55}
56
57#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
58#[serde(deny_unknown_fields)]
59pub struct ExecutionCandidateDescriptor {
60 pub identity: String,
61 pub region: Option<RegionId>,
62 pub kind: ExecutionCandidateKind,
63 pub execution_location: CandidateExecutionLocation,
64 pub preparation: CandidatePreparationState,
65 pub cost: ExecutionCostEstimate,
66 pub output_residency: CandidateOutputResidency,
67 pub guards: Vec<RegionGuardId>,
68}
69
70impl ExecutionCandidateDescriptor {
71 pub fn validate(&self) -> Result<(), &'static str> {
72 if self.identity.is_empty()
73 || self.identity.len() > 128
74 || self.identity.chars().any(char::is_control)
75 {
76 return Err("candidate identity must be 1..=128 bytes without control characters");
77 }
78 if self.cost.checked_total_ns().is_none() {
79 return Err("candidate cost components overflow u64");
80 }
81 if self.kind.is_provider()
82 != matches!(
83 self.execution_location,
84 CandidateExecutionLocation::Provider { .. }
85 )
86 {
87 return Err("candidate kind and execution location are inconsistent");
88 }
89 if self.guards.windows(2).any(|pair| pair[0] >= pair[1]) {
90 return Err("candidate guards must be sorted and unique");
91 }
92 if self
93 .region
94 .is_some_and(|region| self.guards.iter().any(|guard| guard.region != region))
95 {
96 return Err("candidate guards must belong to the candidate region");
97 }
98 Ok(())
99 }
100}