metrale_model_layers/layers/ops/
gemv_sw.rs1use anyhow::Result;
14use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
15use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
16
17use crate::weight_map::QuantizedWeight;
18
19pub const W4A16_GEMV_OUTS_PER_BLOCK: u32 = 4;
22
23pub const W4A16_GEMV_SW_OUTS_PER_BLOCK: u32 = 8;
26
27pub fn w4a16_gemv_grid_x(n: u32) -> u32 {
28 div_ceil(n, W4A16_GEMV_OUTS_PER_BLOCK)
29}
30
31pub fn w4a16_gemv_sw_grid_x(n: u32) -> u32 {
32 div_ceil(n, W4A16_GEMV_SW_OUTS_PER_BLOCK)
33}
34
35pub fn gemv_sw_from(no_gemv_sw: Option<&str>) -> bool {
39 no_gemv_sw != Some("1")
40}
41
42pub fn use_gemv_sw(lever: bool, sw_handle: KernelHandle) -> bool {
45 lever && sw_handle.0 != 0
46}
47
48#[allow(clippy::too_many_arguments)]
50pub fn w4a16_gemv_sw(
51 gpu: &dyn GpuBackend,
52 kernel: KernelHandle,
53 input: DevicePtr,
54 weight: &QuantizedWeight,
55 output: DevicePtr,
56 n: u32,
57 k: u32,
58 stream: u64,
59) -> Result<()> {
60 KernelLaunch::new(gpu, kernel)
61 .grid([w4a16_gemv_sw_grid_x(n), 1, 1])
62 .block([256, 1, 1])
63 .arg_ptr(input)
64 .arg_ptr(weight.weight)
65 .arg_ptr(weight.weight_scale)
66 .arg_f32(weight.weight_scale_2)
67 .arg_ptr(output)
68 .arg_u32(n)
69 .arg_u32(k)
70 .launch(stream)
71}
72
73#[allow(clippy::too_many_arguments)]
78pub fn w4a16_gemv_sw_raw(
79 gpu: &dyn GpuBackend,
80 kernel: KernelHandle,
81 input: DevicePtr,
82 packed: DevicePtr,
83 scale: DevicePtr,
84 scale_2: f32,
85 output: DevicePtr,
86 n: u32,
87 k: u32,
88 stream: u64,
89) -> Result<()> {
90 KernelLaunch::new(gpu, kernel)
91 .grid([w4a16_gemv_sw_grid_x(n), 1, 1])
92 .block([256, 1, 1])
93 .arg_ptr(input)
94 .arg_ptr(packed)
95 .arg_ptr(scale)
96 .arg_f32(scale_2)
97 .arg_ptr(output)
98 .arg_u32(n)
99 .arg_u32(k)
100 .launch(stream)
101}
102
103#[allow(clippy::too_many_arguments)]
106pub fn w4a16_decode_gemv(
107 gpu: &dyn GpuBackend,
108 gemv: KernelHandle,
109 gemv_sw: KernelHandle,
110 use_sw: bool,
111 input: DevicePtr,
112 weight: &QuantizedWeight,
113 output: DevicePtr,
114 n: u32,
115 k: u32,
116 stream: u64,
117) -> Result<()> {
118 if use_gemv_sw(use_sw, gemv_sw) {
119 w4a16_gemv_sw(gpu, gemv_sw, input, weight, output, n, k, stream)
120 } else {
121 super::quant_dispatch::w4a16_gemv(gpu, gemv, input, weight, output, n, k, stream)
122 }
123}
124
125#[cfg(test)]
126#[path = "gemv_sw_tests.rs"]
127mod tests;