metrale_model_arch/moe_v41/
init.rs1use anyhow::{Result, ensure};
14use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend};
15
16use super::{GEMM_MODULE, Kernels, MODULE, MoeV41, MoeV41Cfg, MoeV41Timing, SLOT_TABLE_LAYERS};
17use metrale_model_layers::layers::ops::{
18 KQUANT_MODULE, kquant_mmq_act_bytes, kquant_q8_1_rows_bytes,
19};
20
21impl MoeV41 {
22 pub fn new(gpu: &dyn GpuBackend, cfg: MoeV41Cfg) -> Result<Self> {
23 ensure!(
24 cfg.dim.is_multiple_of(256) && cfg.inter.is_multiple_of(256),
25 "K-quant experts need dim and inter to be multiples of 256 (got {} / {})",
26 cfg.dim,
27 cfg.inter
28 );
29 let m = cfg.max_tokens;
30 let me = m.max(cfg.topk);
35 let alloc = |bytes: usize| gpu.alloc(bytes.max(16));
36 let experts_warps: u32 = std::env::var("METRALE_DS41_EXPERT_WARPS")
42 .ok()
43 .and_then(|v| v.parse().ok())
44 .filter(|w| matches!(w, 2 | 4 | 8))
45 .unwrap_or(8);
46 let sfx = match experts_warps {
47 2 => "2",
48 8 => "8",
49 _ => "",
50 };
51 Ok(MoeV41 {
52 last: std::cell::Cell::new(MoeV41Timing::default()),
53 timing_sync: std::env::var("METRALE_DS41_DIAG").is_ok_and(|v| v == "1"),
54 k: Kernels {
55 gemm: gpu.kernel(GEMM_MODULE, "dense_gemm_bf16")?,
56 gemv: gpu.kernel("gemv", "dense_gemv_bf16")?,
57 gemm_f32out: gpu.kernel(GEMM_MODULE, "dense_gemm_bf16_f32out")?,
58 router_gemv: gpu.kernel(MODULE, "moe_v41_router_gemv_f32out")?,
59 router_gemv_staged: gpu.kernel(MODULE, "moe_v41_router_gemv_f32out_products")?,
60 q8_rows: gpu.kernel(KQUANT_MODULE, "kquant_q8_1_rows_bf16")?,
61 mmvq_q2k: gpu.kernel(KQUANT_MODULE, "kquant_mmvq_q2_k_w")?,
62 mmvq_q3k: gpu.kernel(KQUANT_MODULE, "kquant_mmvq_q3_k_w")?,
63 mmvq_q2k_experts: gpu
64 .kernel(KQUANT_MODULE, &format!("kquant_mmvq_q2_k_experts_w{sfx}"))?,
65 mmvq_q3k_experts: gpu
66 .kernel(KQUANT_MODULE, &format!("kquant_mmvq_q3_k_experts_w{sfx}"))?,
67 experts_warps,
68 swiglu: gpu.kernel(MODULE, "moe_v41_swiglu")?,
69 swiglu_q8: gpu.kernel(KQUANT_MODULE, "kquant_swiglu_q8_1_rows_bf16")?,
70 accumulate: gpu.kernel(MODULE, "moe_v41_accumulate")?,
71 finish: gpu.kernel(MODULE, "moe_v41_finish")?,
72 gather: gpu.kernel(MODULE, "moe_v41_gather_rows")?,
73 scatter_add: gpu.kernel(MODULE, "moe_v41_scatter_add")?,
74 sum_rows: gpu.kernel(MODULE, "moe_v41_sum_rows")?,
75 quant_d2s6: gpu.kernel(KQUANT_MODULE, "metrale_q8_1_quantize_d2s6_bf16")?,
76 quant_d4: gpu.kernel(KQUANT_MODULE, "metrale_q8_1_quantize_d4_bf16")?,
77 mmq_q2k_nc: gpu.kernel(KQUANT_MODULE, "metrale_q2_k_mmq128_nc")?,
78 mmq_q2k_wc: gpu.kernel(KQUANT_MODULE, "metrale_q2_k_mmq128_wc")?,
79 mmq_q3k_nc: gpu.kernel(KQUANT_MODULE, "metrale_q3_k_mmq128_nc")?,
80 mmq_q3k_wc: gpu.kernel(KQUANT_MODULE, "metrale_q3_k_mmq128_wc")?,
81 route_select: gpu.kernel(MODULE, "moe_v41_route_select")?,
82 slot_table_set: gpu.kernel(MODULE, "moe_v41_slot_table_set")?,
83 },
84 logits: alloc(m * cfg.n_routed * 4)?,
85 pred_logits: alloc(cfg.n_routed * 4)?,
86 a_rows: alloc(m * cfg.dim * 2)?,
87 a_q8: alloc(
88 kquant_mmq_act_bytes(m as u32, cfg.dim as u32)
89 .max(kquant_q8_1_rows_bytes(m as u32, cfg.dim as u32)),
90 )?,
91 gate_out: alloc(2 * me * cfg.inter * 2)?,
95 up_out: alloc(me * cfg.inter * 2)?,
96 h: alloc(me * cfg.inter * 2)?,
97 h_q8: alloc(
98 kquant_mmq_act_bytes(me as u32, cfg.inter as u32)
99 .max(kquant_q8_1_rows_bytes(me as u32, cfg.inter as u32)),
100 )?,
101 down_out: alloc(me * cfg.dim * 2)?,
102 rows_dev: alloc(m * cfg.topk * 4)?,
103 weight_dev: alloc(m * cfg.topk * 4)?,
104 route_hdr: alloc(SLOT_TABLE_LAYERS * (1 + 3 * cfg.topk) * 4)?,
105 slot_table: {
106 let t = alloc(SLOT_TABLE_LAYERS * cfg.n_routed * 4)?;
107 gpu.memset(t, 0xFF, SLOT_TABLE_LAYERS * cfg.n_routed * 4)?;
108 t
109 },
110 ptrs_dev: alloc(3 * cfg.topk * 8)?,
111 sg: alloc(m * cfg.inter * 2)?,
112 su: alloc(m * cfg.inter * 2)?,
113 sh: alloc(m * cfg.inter * 2)?,
114 sd: alloc(m * cfg.dim * 2)?,
115 acc: alloc(m * cfg.dim * 4)?,
116 out: alloc(m * cfg.dim * 2)?,
117 sh_q8: alloc(kquant_q8_1_rows_bytes(1, cfg.inter as u32))?,
118 side: gpu.create_stream()?,
119 ev_in: gpu.create_event()?,
120 ev_out: gpu.create_event()?,
121 cfg,
122 })
123 }
124
125 pub fn out_ptr(&self) -> DevicePtr {
126 self.out
127 }
128
129 pub fn free(self, gpu: &dyn GpuBackend) -> Result<()> {
130 for p in [
131 self.logits,
132 self.pred_logits,
133 self.a_rows,
134 self.a_q8,
135 self.rows_dev,
136 self.route_hdr,
137 self.slot_table,
138 self.gate_out,
139 self.up_out,
140 self.h,
141 self.h_q8,
142 self.down_out,
143 self.weight_dev,
144 self.sg,
145 self.su,
146 self.sh,
147 self.sd,
148 self.acc,
149 self.out,
150 self.sh_q8,
151 ] {
152 gpu.free(p)?;
153 }
154 gpu.destroy_event(self.ev_in)?;
155 gpu.destroy_event(self.ev_out)?;
156 Ok(())
157 }
158}