1use std::rc::Rc;
4
5use pagesift_infer::exec::{Exec, attention_scale};
6use pagesift_infer::{Activation, Conv2d, ConvTranspose2d, LayerNorm, Linear};
7
8use crate::buffer::Args;
9use crate::exec::{BatchExec, DevTensor};
10use crate::ops::ConvShape;
11
12fn chw(x: &DevTensor<'_, '_>) -> (usize, usize, usize) {
14 assert_eq!(x.shape.len(), 3, "需要 [C, H, W],实际 {:?}", x.shape);
16 (x.shape[0], x.shape[1], x.shape[2])
17}
18
19fn tc(x: &DevTensor<'_, '_>) -> (usize, usize) {
21 assert_eq!(x.shape.len(), 2, "需要 [T, C],实际 {:?}", x.shape);
22 (x.shape[0], x.shape[1])
23}
24
25fn map_widths(w: &[u32], f: impl Fn(usize) -> usize) -> Rc<Vec<u32>> {
27 Rc::new(w.iter().map(|&v| f(v as usize) as u32).collect())
28}
29
30impl<'c, 'g> BatchExec<'c, 'g> {
31 fn elems(&self, shape: &[usize]) -> usize {
32 self.n * shape.iter().product::<usize>()
33 }
34
35 fn new_tensor(&self, shape: Vec<usize>, widths: Rc<Vec<u32>>) -> DevTensor<'c, 'g> {
36 let len = self.elems(&shape);
37 self.alloc(len, shape, widths)
38 }
39}
40
41impl<'c, 'g> BatchExec<'c, 'g> {
42 fn conv_implicit(
46 &self,
47 l: &Conv2d,
48 x: &DevTensor<'c, 'g>,
49 s: &ConvShape,
50 out: &DevTensor<'c, 'g>,
51 bias: Option<u64>,
52 ) {
53 let (oh, ow) = s.out_hw();
54 let (nh, nw) = (s.h + 2 * s.pad.0, s.w + 2 * s.pad.1);
55 let none = || Rc::new(Vec::new());
56 let k = &self.ctx.gpu.k;
57 let padded = self.new_tensor(vec![s.c, nh, nw], none());
58 let total = self.elems(&padded.shape);
59 let args = Args::default()
60 .raw_ptr(x.ptr())
61 .raw_ptr(padded.ptr())
62 .u32(self.n * s.c)
63 .u32(s.h)
64 .u32(s.w)
65 .u32(s.pad.0)
66 .u32(s.pad.1)
67 .u32(nh)
68 .u32(nw);
69 self.d1(k.pad_all, total, args);
70 let cols = (oh - 1) * nw + ow;
71 let wide = self.new_tensor(vec![s.o, cols], none());
72 let wt = self.weight_kernel_first(l);
73 let per_k = s.o * s.c; let ldb = nh * nw;
75 for (i, (ky, kx)) in (0..s.kh)
76 .flat_map(|ky| (0..s.kw).map(move |kx| (ky, kx)))
77 .enumerate()
78 {
79 if !self.live() {
80 break;
81 }
82 let (a, b) = (
83 wt + bytes_of(i * per_k),
84 padded.ptr() + bytes_of(ky * nw + kx),
85 );
86 self.check(self.ctx.gpu.sgemm_ext(
87 a,
88 b,
89 wide.ptr(),
90 (s.o, cols, s.c),
91 ldb,
92 i > 0,
93 self.n,
94 (0, s.c * ldb, s.o * cols),
95 ));
96 }
97 let total = self.elems(&out.shape);
98 let args = Args::default()
99 .raw_ptr(wide.ptr())
100 .raw_ptr(out.ptr())
101 .u32(cols)
102 .u32(nw)
103 .u32(oh)
104 .u32(ow)
105 .u32(total);
106 self.d1(k.crop_cols, total, args);
107 if let Some(b) = bias {
108 let args = Args::default()
109 .raw_ptr(out.ptr())
110 .raw_ptr(b)
111 .u32(oh * ow)
112 .u32(s.o)
113 .u32(total);
114 self.d1(k.add_bias, total, args);
115 }
116 }
117}
118
119impl<'c, 'g> Exec for BatchExec<'c, 'g> {
120 type T = DevTensor<'c, 'g>;
121
122 fn shape(&self, x: &Self::T) -> Vec<usize> {
123 x.shape.clone()
124 }
125
126 fn conv(&self, l: &Conv2d, x: &Self::T) -> Self::T {
127 let (c, h, w) = chw(x);
128 let s = ConvShape {
129 c,
130 h,
131 w,
132 o: l.weight.shape[0],
133 kh: l.weight.shape[2],
134 kw: l.weight.shape[3],
135 stride: l.stride,
136 pad: l.pad,
137 dilation: l.dilation,
138 groups: l.groups,
139 };
140 let (oh, ow) = s.out_hw();
141 let widths = map_widths(&x.widths, |v| {
142 (v + 2 * s.pad.1 - s.dilation.1 * (s.kw - 1) - 1) / s.stride.1 + 1
143 });
144 let out = self.new_tensor(vec![s.o, oh, ow], widths);
145 let bias = l.bias.as_deref().map(|b| self.weight(b));
146 if s.implicit() {
147 self.conv_implicit(l, x, &s, &out, bias);
148 self.mask(&out);
149 return out;
150 }
151 let wt = self.weight(&l.weight.data);
152 let col = s.needs_col().then(|| {
154 let len = self.n * s.col_len();
155 self.alloc(len, vec![len], Rc::default())
156 });
157 if self.live() {
158 self.check(self.ctx.gpu.conv_raw(
159 x.ptr(),
160 wt,
161 bias,
162 &s,
163 self.n,
164 out.ptr(),
165 col.as_ref().map(|t| t.ptr()),
166 ));
167 }
168 drop(col);
169 self.mask(&out);
170 out
171 }
172
173 fn conv_transpose(&self, l: &ConvTranspose2d, x: &Self::T) -> Self::T {
174 let (c, h, w) = chw(x);
175 let (o, kh, kw) = (l.weight.shape[1], l.weight.shape[2], l.weight.shape[3]);
176 let oh = (h - 1) * l.stride.0 + kh - 2 * l.pad.0;
177 let ow = (w - 1) * l.stride.1 + kw - 2 * l.pad.1;
178 let widths = map_widths(&x.widths, |v| (v - 1) * l.stride.1 + kw - 2 * l.pad.1);
179 let out = self.new_tensor(vec![o, oh, ow], widths);
180 let wt = self.weight(&l.weight.data);
181 let bias = l.bias.as_deref().map_or(0, |b| self.weight(b));
182 let total = self.elems(&out.shape);
183 let args = Args::default()
184 .raw_ptr(x.ptr())
185 .raw_ptr(wt)
186 .raw_ptr(bias)
187 .raw_ptr(out.ptr())
188 .u32(c)
189 .u32(o)
190 .u32(l.bias.is_some() as usize)
191 .u32(h)
192 .u32(w)
193 .u32(kh)
194 .u32(kw)
195 .u32(l.stride.0)
196 .u32(l.stride.1)
197 .u32(l.pad.0)
198 .u32(l.pad.1)
199 .u32(oh)
200 .u32(ow)
201 .u32(total);
202 self.d1(self.ctx.gpu.k.conv_transpose, total, args);
203 self.mask(&out);
204 out
205 }
206
207 fn act(&self, a: Activation, x: &mut Self::T) {
208 let k = &self.ctx.gpu.k;
209 let f = match a {
210 Activation::Identity => return,
211 Activation::Relu => k.relu,
212 Activation::Silu => k.silu,
213 Activation::Gelu => k.gelu,
214 Activation::HardSigmoid => k.hardsigmoid,
215 Activation::Sigmoid => k.sigmoid,
216 };
217 let total = self.elems(&x.shape);
218 self.d1(f, total, Args::default().raw_ptr(x.ptr()).u32(total));
219 if a.apply(0.0) != 0.0 && x.shape.len() == 3 {
222 self.mask(x);
223 }
224 }
225
226 fn add(&self, a: &Self::T, b: &Self::T) -> Self::T {
227 assert_eq!(a.shape, b.shape, "相加的形状不同");
228 let out = self.new_tensor(a.shape.clone(), a.widths.clone());
229 let total = self.elems(&a.shape);
230 let args = Args::default()
231 .raw_ptr(a.ptr())
232 .raw_ptr(b.ptr())
233 .raw_ptr(out.ptr())
234 .u32(total);
235 self.d1(self.ctx.gpu.k.add2, total, args);
236 out
237 }
238
239 fn add_assign(&self, a: &mut Self::T, b: &Self::T) {
240 assert_eq!(a.shape, b.shape, "相加的形状不同");
241 let total = self.elems(&a.shape);
242 let args = Args::default()
243 .raw_ptr(a.ptr())
244 .raw_ptr(b.ptr())
245 .raw_ptr(a.ptr())
246 .u32(total);
247 self.d1(self.ctx.gpu.k.add2, total, args);
248 }
249
250 fn pad_right_bottom(&self, x: &Self::T, right: usize, bottom: usize) -> Self::T {
251 let (c, h, w) = chw(x);
252 let (nh, nw) = (h + bottom, w + right);
253 let out = self.new_tensor(vec![c, nh, nw], map_widths(&x.widths, |v| v + right));
254 let total = self.elems(&out.shape);
255 let args = Args::default()
256 .raw_ptr(x.ptr())
257 .raw_ptr(out.ptr())
258 .u32(self.n * c)
259 .u32(h)
260 .u32(w)
261 .u32(nh)
262 .u32(nw);
263 self.d1(self.ctx.gpu.k.pad_rb, total, args);
264 out
265 }
266
267 fn max_pool2d(
268 &self,
269 x: &Self::T,
270 k: (usize, usize),
271 stride: (usize, usize),
272 ceil_mode: bool,
273 ) -> Self::T {
274 let (c, h, w) = chw(x);
275 let size = |n: usize, k: usize, s: usize| {
277 if ceil_mode {
278 let o = (n - k).div_ceil(s) + 1;
279 if (o - 1) * s >= n { o - 1 } else { o }
280 } else {
281 (n - k) / s + 1
282 }
283 };
284 let (oh, ow) = (size(h, k.0, stride.0), size(w, k.1, stride.1));
285 let out = self.new_tensor(
286 vec![c, oh, ow],
287 map_widths(&x.widths, |v| size(v, k.1, stride.1)),
288 );
289 let total = self.elems(&out.shape);
290 let args = Args::default()
291 .raw_ptr(x.ptr())
292 .raw_ptr(out.ptr())
293 .u32(self.n * c)
294 .u32(h)
295 .u32(w)
296 .u32(k.0)
297 .u32(k.1)
298 .u32(stride.0)
299 .u32(stride.1)
300 .u32(oh)
301 .u32(ow);
302 self.d1(self.ctx.gpu.k.pool_max, total, args);
303 self.mask(&out);
304 out
305 }
306
307 fn avg_pool2d(&self, x: &Self::T, k: (usize, usize)) -> Self::T {
308 let (c, h, w) = chw(x);
309 let (oh, ow) = (h / k.0, w / k.1);
310 let out = self.new_tensor(vec![c, oh, ow], map_widths(&x.widths, |v| v / k.1));
311 let total = self.elems(&out.shape);
312 let args = Args::default()
313 .raw_ptr(x.ptr())
314 .raw_ptr(out.ptr())
315 .u32(self.n * c)
316 .u32(h)
317 .u32(w)
318 .u32(k.0)
319 .u32(k.1)
320 .u32(oh)
321 .u32(ow);
322 self.d1(self.ctx.gpu.k.pool_avg, total, args);
323 self.mask(&out);
324 out
325 }
326
327 fn global_avg(&self, x: &Self::T) -> Self::T {
328 let (c, h, w) = chw(x);
329 let out = self.new_tensor(vec![c, 1, 1], Rc::new(vec![1; self.n]));
330 let total = self.n * c;
331 let args = Args::default()
332 .raw_ptr(x.ptr())
333 .raw_ptr(out.ptr())
334 .raw_ptr(self.widths_ptr(&x.widths))
335 .u32(c)
336 .u32(h)
337 .u32(w)
338 .u32(total);
339 self.d1(self.ctx.gpu.k.global_avg, total, args);
340 out
341 }
342
343 fn scale_channels(&self, x: &mut Self::T, s: &Self::T) {
344 let (_, h, w) = chw(x);
345 let total = self.elems(&x.shape);
346 let args = Args::default()
347 .raw_ptr(x.ptr())
348 .raw_ptr(s.ptr())
349 .u32(h * w)
350 .u32(total);
351 self.d1(self.ctx.gpu.k.scale_ch, total, args);
352 }
353
354 fn se_gate(&self, s: &mut Self::T) {
355 let total = self.elems(&s.shape);
356 let args = Args::default().raw_ptr(s.ptr()).u32(total);
357 self.d1(self.ctx.gpu.k.se_gate, total, args);
358 }
359
360 fn concat(&self, xs: &[&Self::T]) -> Self::T {
361 let (_, h, w) = chw(xs[0]);
362 let c: usize = xs.iter().map(|x| chw(x).0).sum();
363 let out = self.new_tensor(vec![c, h, w], xs[0].widths.clone());
364 let stride = c * h * w;
365 let mut at = 0usize;
366 for x in xs {
367 let (xc, xh, xw) = chw(x);
368 assert_eq!((xh, xw), (h, w), "拼接的张量尺寸不同");
369 let len = xc * h * w;
370 let args = Args::default()
371 .raw_ptr(x.ptr())
372 .raw_ptr(out.ptr() + bytes_of(at))
373 .u32(len)
374 .u32(stride)
375 .u32(self.n * len);
376 self.d1(self.ctx.gpu.k.copy_part, self.n * len, args);
377 at += len;
378 }
379 out
380 }
381
382 fn upsample(&self, x: &Self::T, oh: usize, ow: usize) -> Self::T {
383 let (c, h, w) = chw(x);
384 let out = self.new_tensor(
385 vec![c, oh, ow],
386 map_widths(&x.widths, |v| (v * ow).div_ceil(w)),
387 );
388 let total = self.elems(&out.shape);
389 let args = Args::default()
390 .raw_ptr(x.ptr())
391 .raw_ptr(out.ptr())
392 .u32(self.n * c)
393 .u32(h)
394 .u32(w)
395 .u32(oh)
396 .u32(ow);
397 self.d1(self.ctx.gpu.k.interp_nearest, total, args);
398 self.mask(&out);
399 out
400 }
401
402 fn chw_to_seq(&self, x: &Self::T) -> Self::T {
403 let (c, h, w) = chw(x);
404 assert!(
405 h == 1 || x.widths.iter().all(|&v| v as usize == w),
406 "高不为 1 时各样本要一样宽,序列长度才说得清"
407 );
408 let hw = h * w;
409 let out = self.new_tensor(vec![hw, c], map_widths(&x.widths, |v| v * h));
410 let total = self.elems(&out.shape);
411 let args = Args::default()
412 .raw_ptr(x.ptr())
413 .raw_ptr(out.ptr())
414 .u32(c)
415 .u32(hw)
416 .u32(total);
417 self.d1(self.ctx.gpu.k.chw_to_seq, total, args);
418 out
419 }
420
421 fn linear(&self, l: &Linear, x: &Self::T) -> Self::T {
422 let (t, k) = tc(x);
423 let (kb, o) = (l.weight_t.shape[0], l.weight_t.shape[1]);
424 assert_eq!(k, kb, "矩阵乘的内维不同");
425 let out = self.new_tensor(vec![t, o], x.widths.clone());
426 let wt = self.weight(&l.weight_t.data);
427 let bias = l.bias.as_deref().map(|b| self.weight(b));
428 if self.live() {
429 self.check(self.ctx.gpu.sgemm_raw(
430 x.ptr(),
431 wt,
432 out.ptr(),
433 (t, o, k),
434 self.n,
435 (t * k, 0, t * o),
436 ));
437 }
438 if let Some(b) = bias {
439 let total = self.elems(&out.shape);
441 let args = Args::default()
442 .raw_ptr(out.ptr())
443 .raw_ptr(b)
444 .u32(1)
445 .u32(o)
446 .u32(total);
447 self.d1(self.ctx.gpu.k.add_bias, total, args);
448 }
449 out
450 }
451
452 fn layer_norm(&self, l: &LayerNorm, x: &Self::T) -> Self::T {
453 let (t, c) = tc(x);
454 let out = self.new_tensor(vec![t, c], x.widths.clone());
455 let (wt, bias) = (self.weight(&l.weight), self.weight(&l.bias));
456 let rows = self.n * t;
457 let args = Args::default()
458 .raw_ptr(x.ptr())
459 .raw_ptr(out.ptr())
460 .raw_ptr(wt)
461 .raw_ptr(bias)
462 .f32(l.eps)
463 .u32(c)
464 .u32(rows);
465 self.d1(self.ctx.gpu.k.layer_norm, rows, args);
466 out
467 }
468
469 fn attention(&self, qkv: &Self::T, heads: usize) -> Self::T {
470 let (t, c3) = tc(qkv);
471 let c = c3 / 3; let hd = c / heads;
473 let nh = self.n * heads;
474 let k = &self.ctx.gpu.k;
475 let none = || Rc::new(Vec::new());
476 let q = self.new_tensor(vec![heads, t, hd], none());
477 let kt = self.new_tensor(vec![heads, hd, t], none());
478 let v = self.new_tensor(vec![heads, t, hd], none());
479 let total = nh * t * hd;
480 let args = Args::default()
481 .raw_ptr(qkv.ptr())
482 .raw_ptr(q.ptr())
483 .raw_ptr(kt.ptr())
484 .raw_ptr(v.ptr())
485 .u32(t)
486 .u32(heads)
487 .u32(hd)
488 .u32(total);
489 self.d1(k.attn_split, total, args);
490 let a = self.new_tensor(vec![heads, t, t], none());
491 if self.live() {
492 self.check(self.ctx.gpu.sgemm_raw(
493 q.ptr(),
494 kt.ptr(),
495 a.ptr(),
496 (t, t, hd),
497 nh,
498 (t * hd, hd * t, t * t),
499 ));
500 }
501 drop((q, kt));
502 let rows = nh * t;
503 let args = Args::default()
504 .raw_ptr(a.ptr())
505 .raw_ptr(self.widths_ptr(&qkv.widths))
506 .f32(attention_scale(hd))
507 .u32(t)
508 .u32(heads)
509 .u32(rows);
510 self.d1(k.attn_softmax, rows, args);
511 let o = self.new_tensor(vec![heads, t, hd], none());
512 if self.live() {
513 self.check(self.ctx.gpu.sgemm_raw(
514 a.ptr(),
515 v.ptr(),
516 o.ptr(),
517 (t, hd, t),
518 nh,
519 (t * t, t * hd, t * hd),
520 ));
521 }
522 drop((a, v));
523 let out = self.new_tensor(vec![t, c], qkv.widths.clone());
524 let total = self.elems(&out.shape);
525 let args = Args::default()
526 .raw_ptr(o.ptr())
527 .raw_ptr(out.ptr())
528 .u32(t)
529 .u32(heads)
530 .u32(hd)
531 .u32(total);
532 self.d1(k.attn_merge, total, args);
533 out
534 }
535
536 fn ctc_digest(&self, logits: &Self::T) -> Vec<Vec<(u32, f32)>> {
537 let (t, n) = tc(logits);
538 let rows = self.n * t;
539 let out = self.new_tensor(vec![t, 2], logits.widths.clone());
540 let args = Args::default()
541 .raw_ptr(logits.ptr())
542 .raw_ptr(out.ptr())
543 .u32(n)
544 .u32(rows);
545 self.d1(self.ctx.gpu.k.ctc_digest, rows, args);
546 if !self.live() {
547 return vec![Vec::new(); self.n];
548 }
549 let host = match self.download(&out) {
550 Ok(h) => h,
551 Err(e) => {
552 self.fail(e);
553 return vec![Vec::new(); self.n];
554 }
555 };
556 logits
557 .widths
558 .iter()
559 .enumerate()
560 .map(|(z, &len)| {
561 host[z * t * 2..(z * t + len as usize) * 2]
562 .as_chunks::<2>()
563 .0
564 .iter()
565 .map(|p| (p[0].to_bits(), p[1]))
566 .collect()
567 })
568 .collect()
569 }
570}
571
572fn bytes_of(n: usize) -> u64 {
574 crate::pool::bytes(n)
575}