1use std::collections::hash_map::DefaultHasher;
12use std::hash::{Hash, Hasher};
13
14use crate::logical_kernel::KernelDispatchConfig;
15use crate::quant::QuantScheme;
16use crate::variant::ModelVariant;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
20pub enum CompilationMode {
21 #[default]
23 Eager,
24 Lazy,
26 Aot,
28}
29
30#[derive(Debug, Clone)]
32pub struct ModelComponent {
33 pub variant: ModelVariant,
34 pub kernel_dispatch: KernelDispatchConfig,
35 pub compilation_mode: CompilationMode,
36 pub profile_key: u64,
38 pub quant: Option<QuantScheme>,
40 pub layer_composition_key: u64,
42}
43
44impl ModelComponent {
45 pub fn new(variant: ModelVariant) -> Self {
46 Self {
47 variant,
48 kernel_dispatch: KernelDispatchConfig::default(),
49 compilation_mode: CompilationMode::Eager,
50 profile_key: 0,
51 quant: None,
52 layer_composition_key: 0,
53 }
54 }
55
56 pub fn with_kernel_dispatch(mut self, config: KernelDispatchConfig) -> Self {
57 self.kernel_dispatch = config;
58 self
59 }
60
61 pub fn with_compilation_mode(mut self, mode: CompilationMode) -> Self {
62 self.compilation_mode = mode;
63 self
64 }
65
66 pub fn with_profile_key(mut self, key: u64) -> Self {
67 self.profile_key = key;
68 self
69 }
70
71 pub fn with_quant(mut self, scheme: QuantScheme) -> Self {
72 self.quant = Some(scheme);
73 self
74 }
75
76 pub fn with_layer_composition_key(mut self, key: u64) -> Self {
77 self.layer_composition_key = key;
78 self
79 }
80
81 pub fn cache_key(&self) -> u64 {
83 let mut h = DefaultHasher::new();
84 self.variant.cache_key().hash(&mut h);
85 (self.kernel_dispatch.policy as u8).hash(&mut h);
86 for k in self.kernel_dispatch.force_common_kinds.iter() {
87 k.hash(&mut h);
88 }
89 for k in self.kernel_dispatch.force_native_kinds.iter() {
90 k.hash(&mut h);
91 }
92 self.compilation_mode.hash(&mut h);
93 self.profile_key.hash(&mut h);
94 if let Some(q) = &self.quant {
95 format!("{q:?}").hash(&mut h);
96 }
97 self.layer_composition_key.hash(&mut h);
98 h.finish()
99 }
100
101 pub fn dim_binding(&self) -> crate::DimBinding {
102 self.variant.dim_binding()
103 }
104
105 pub fn aot_disk_base(&self) -> String {
107 format!("rlx_{:016x}", self.cache_key())
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::ModelVariant;
115 use crate::logical_kernel::KernelDispatchPolicy;
116
117 #[test]
118 fn cache_key_changes_with_mode_and_profile() {
119 let v = ModelVariant::prefill(1, 8);
120 let a = ModelComponent::new(v.clone()).cache_key();
121 let b = ModelComponent::new(v.clone())
122 .with_compilation_mode(CompilationMode::Lazy)
123 .cache_key();
124 let c = ModelComponent::new(v)
125 .with_profile_key(42)
126 .with_kernel_dispatch(KernelDispatchConfig::new(KernelDispatchPolicy::ForceCommon))
127 .cache_key();
128 assert_ne!(a, b);
129 assert_ne!(a, c);
130 }
131}