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