ferrox_models/
execution_plan.rs1use crate::capability::{DecoderFamily, MemoryKind, QkNormStyle};
8use crate::config::{FfnActivation, RopeLayout};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
12pub struct FusedOpCaps {
13 pub metal_flash_attn: bool,
14 pub metal_swiglu: bool,
15 pub metal_matvec: bool,
16 pub cuda_gqa: bool,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct MemoryPlan {
23 pub kind: MemoryKind,
24 pub swa_pattern: Option<usize>,
25 pub sliding_window: Option<usize>,
26}
27
28#[derive(Debug, Clone, PartialEq)]
31pub struct ExecutionPlan {
32 pub family: DecoderFamily,
33 pub rope: RopeLayout,
34 pub qk_norm: QkNormStyle,
35 pub ffn_activation: FfnActivation,
36 pub memory: MemoryPlan,
37 pub fused: FusedOpCaps,
38 pub embedding_scale: Option<f32>,
39 pub attention_scale: Option<f32>,
40 pub rope_theta_swa: Option<f32>,
41 pub attn_logit_softcap: Option<f32>,
42 pub final_logit_softcap: Option<f32>,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub struct PlanGeometry {
48 pub n_tokens: usize,
49 pub n_seqs: usize,
50 pub flash_attn: bool,
51}
52
53impl ExecutionPlan {
54 pub fn from_config(
56 config: &crate::config::ModelConfig,
57 family: DecoderFamily,
58 memory_kind: MemoryKind,
59 fused: FusedOpCaps,
60 ) -> Self {
61 Self {
62 family,
63 rope: config.rope_layout,
64 qk_norm: config.qk_norm_style,
65 ffn_activation: config.ffn_activation,
66 memory: MemoryPlan {
67 kind: memory_kind,
68 swa_pattern: config.swa_pattern,
69 sliding_window: config.sliding_window,
70 },
71 fused,
72 embedding_scale: config.embedding_scale,
73 attention_scale: config.attention_scale,
74 rope_theta_swa: config.rope_theta_swa,
75 attn_logit_softcap: config.attn_logit_softcap,
76 final_logit_softcap: config.final_logit_softcap,
77 }
78 }
79
80 pub fn probe_metal_caps() -> FusedOpCaps {
83 #[cfg(feature = "metal")]
84 {
85 let metal_on = ferrox_core::metal_dense_enabled();
86 FusedOpCaps {
87 metal_flash_attn: metal_on && ferrox_metal::attn::metal_attn_enabled(),
88 metal_swiglu: metal_on,
89 metal_matvec: metal_on,
90 cuda_gqa: false,
91 }
92 }
93 #[cfg(not(feature = "metal"))]
94 {
95 FusedOpCaps::default()
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::config::test_dense_fixture;
104
105 #[test]
106 fn plan_from_tiny_config_defaults() {
107 let cfg = test_dense_fixture();
108 let plan = ExecutionPlan::from_config(
109 &cfg,
110 DecoderFamily::StandardGqa,
111 MemoryKind::KvGqa,
112 FusedOpCaps::default(),
113 );
114 assert_eq!(plan.family, DecoderFamily::StandardGqa);
115 assert_eq!(plan.qk_norm, QkNormStyle::WholeVector);
116 assert!(!plan.fused.cuda_gqa);
117 }
118}