metrale_model_arch/engram_v41/
apply.rs1use anyhow::{Context, Result, ensure};
15use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend};
16use metrale_gpu_runtime::kernel_args::KernelLaunch;
17
18use super::EngramV41;
19use metrale_model_layers::layers::ops;
20use metrale_model_layers::weight_map::DenseWeight;
21
22impl EngramV41 {
23 pub fn apply(
27 &self,
28 gpu: &dyn GpuBackend,
29 layer: usize,
30 streams: DevicePtr,
31 tokens: usize,
32 stream: u64,
33 ) -> Result<()> {
34 ensure!(
35 tokens <= self.max_tokens,
36 "engram: {tokens} tokens exceeds the {} workspace",
37 self.max_tokens
38 );
39 let w = self
40 .layer(layer)
41 .with_context(|| format!("engram: layer {layer} has no weights"))?;
42 let wkv = DenseWeight { weight: w.wkv };
43 if tokens == 1 && !w.wkv_q2k.is_null() {
44 let (n, k) = (self.out_features() as u32, self.in_features() as u32);
45 ensure!(
46 k.is_multiple_of(256),
47 "engram: in_features {k} is not Q2_K blocks"
48 );
49 KernelLaunch::new(gpu, self.gemv_q2k_k)
50 .grid([n.div_ceil(4), 1, 1])
51 .block([256, 1, 1])
52 .arg_ptr(self.rows_of(w))
53 .arg_ptr(w.wkv_q2k)
54 .arg_ptr(self.kv)
55 .arg_u32(n)
56 .arg_u32(k)
57 .launch(stream)?;
58 } else if tokens == 1 {
59 ops::dense_gemv(
60 gpu,
61 self.gemv_k,
62 self.rows_of(w),
63 &wkv,
64 self.kv,
65 self.out_features() as u32,
66 self.in_features() as u32,
67 stream,
68 )?;
69 } else {
70 ops::dense_gemm(
71 gpu,
72 self.gemm_k,
73 self.rows_of(w),
74 &wkv,
75 self.kv,
76 tokens as u32,
77 self.out_features() as u32,
78 self.in_features() as u32,
79 stream,
80 )?;
81 }
82 KernelLaunch::new(gpu, self.gate_k)
83 .grid([tokens as u32, self.hc as u32, 1])
84 .block([256, 1, 1])
85 .arg_ptr(streams)
86 .arg_ptr(self.kv)
87 .arg_ptr(w.qk)
88 .arg_u32(self.dim as u32)
89 .arg_u32(self.hc as u32)
90 .arg_f32(self.eps)
91 .launch(stream)
92 }
93}