1use taconite::bf16_to_f32;
21
22use crate::cpu::{gelu_bf16, par_rows};
23use crate::npu::pull;
24use crate::{Error, Sam3, gemm, narrow};
25
26impl Sam3 {
27 pub(crate) fn conv3x3(&mut self, x: &[u16], side: usize, wkey: &str, bias: &[f32]) -> Result<Vec<f32>, Error> {
30 let g = self.npu.spec("conv")?;
31 let (k, lda) = (g.k, g.lda);
32 let d = (k - lda) / 2;
33 let c = d / 3;
34 let oc = bias.len();
35 let wp = side + 2;
36 let n = side * wp;
37 let t0 = std::time::Instant::now();
38 let mut ybuf = vec![0u16; n * d];
39 par_rows(&mut ybuf, d, |p0, piece| {
40 for (pi, row) in piece.chunks_mut(d).enumerate() {
41 let p = p0 + pi;
42 for dy in 0..3 {
43 let r = p + dy * wp;
44 let (yy, xx) = (r / wp, r % wp);
45 let dst = &mut row[dy * c..(dy + 1) * c];
46 if (1..=side).contains(&yy) && (1..=side).contains(&xx) {
47 let s = ((yy - 1) * side + xx - 1) * c;
48 dst.copy_from_slice(&x[s..s + c]);
49 } else {
50 dst.fill(0);
51 }
52 }
53 }
54 });
55 let io = self.io.conv.get_mut(&side).ok_or_else(|| Error::Input(format!("no conv buffers for {side} px")))?;
56 io.set_a(&ybuf)?;
57 self.timing.add("conv_in", t0.elapsed());
58 let io = &self.io.conv[&side];
59 gemm(&mut self.npu, io, &self.w[wkey], &mut self.timing)?;
60 let t0 = std::time::Instant::now();
61 let out_bf = pull(&io.c, n * oc)?;
62 let mut out = vec![0f32; side * side * oc];
63 par_rows(&mut out, side * oc, |y0, piece| {
64 for (yi, row) in piece.chunks_mut(side * oc).enumerate() {
65 let src = &out_bf[(y0 + yi) * wp * oc..][..side * oc];
66 for (j, o) in row.iter_mut().enumerate() {
67 *o = bf16_to_f32(src[j]) + bias[j % oc];
68 }
69 }
70 });
71 self.timing.add("conv_out", t0.elapsed());
72 Ok(out)
73 }
74
75 pub fn neck(&mut self, vit: &[f32]) -> Result<[Vec<f32>; 3], Error> {
78 let cfg = self.cfg.clone();
79 let (g, t) = (cfg.grid, cfg.tokens());
80 let (s0, s1, s2) = (cfg.neck_splits[0], cfg.neck_splits[1], cfg.neck_splits[2]);
81 let width = s0 + s1 + s2;
82 let fpn = cfg.d_model;
83 let mut vb = vec![0u16; vit.len()];
84 narrow(vit, &mut vb);
85 self.io.n_in.set_a(&vb)?;
86 gemm(&mut self.npu, &self.io.n_in, &self.w["n.in"], &mut self.timing)?;
87 let t0 = std::time::Instant::now();
88 let y = self.io.n_in.get_c(t)?;
89 let y = &y[..];
90
91 let mid = s0 / 4;
93 let g2 = 2 * g;
94 let mut a0 = vec![0u16; 4 * t * mid];
95 par_rows(&mut a0, mid, |r0, piece| {
96 for (ri, row) in piece.chunks_mut(mid).enumerate() {
97 let r = r0 + ri;
98 let (yy, xx) = (r / g2, r % g2);
99 let src = &y[((yy / 2) * g + xx / 2) * width + ((yy % 2) * 2 + xx % 2) * mid..][..mid];
100 gelu_bf16(src, row);
101 }
102 });
103 let shuffle = |src: &[u16], h: usize, off: usize| -> Vec<u16> {
105 let mut out = vec![0u16; 4 * h * h * fpn];
106 par_rows(&mut out, fpn, |r0, piece| {
107 for (ri, row) in piece.chunks_mut(fpn).enumerate() {
108 let r = r0 + ri;
109 let (yy, xx) = (r / (2 * h), r % (2 * h));
110 let s = ((yy / 2) * h + xx / 2) * width + off + ((yy % 2) * 2 + xx % 2) * fpn;
111 row.copy_from_slice(&src[s..s + fpn]);
112 }
113 });
114 out
115 };
116 let u1 = shuffle(y, g, s0);
117 let mut u2 = vec![0u16; t * fpn];
118 for (p, row) in u2.chunks_mut(fpn).enumerate() {
119 row.copy_from_slice(&y[p * width + s0 + s1..][..fpn]);
120 }
121 self.io.n_up.set_a(&a0)?;
122 self.timing.add("neck_gelu_shuffle", t0.elapsed());
123 gemm(&mut self.npu, &self.io.n_up, &self.w["n.up"], &mut self.timing)?;
124 let t0 = std::time::Instant::now();
125 let up = self.io.n_up.get_c(4 * t)?;
126 let n_up = self.npu.spec("n_up")?.n;
127 let mut u0 = vec![0u16; 16 * t * fpn];
128 {
129 let g4 = 4 * g;
130 par_rows(&mut u0, fpn, |r0, piece| {
131 for (ri, row) in piece.chunks_mut(fpn).enumerate() {
132 let r = r0 + ri;
133 let (yy, xx) = (r / g4, r % g4);
134 let s = ((yy / 2) * g2 + xx / 2) * n_up + ((yy % 2) * 2 + xx % 2) * fpn;
135 row.copy_from_slice(&up[s..s + fpn]);
136 }
137 });
138 }
139 self.timing.add("neck_up_shuffle", t0.elapsed());
140 let b: Vec<Vec<f32>> =
141 (0..3).map(|i| self.store.f32(&format!("n.conv{i}.b")).map(<[f32]>::to_vec)).collect::<Result<_, _>>()?;
142 let f0 = self.conv3x3(&u0, 4 * g, "n.conv0", &b[0])?;
143 let f1 = self.conv3x3(&u1, 2 * g, "n.conv1", &b[1])?;
144 let f2 = self.conv3x3(&u2, g, "n.conv2", &b[2])?;
145 Ok([f0, f1, f2])
146 }
147}