metrale_model_layers/layers/ops/
dispatch_proj.rs1#![allow(unused_imports)]
12
13use super::*;
14
15#[path = "dispatch_proj/cutlass.rs"]
19mod cutlass;
20pub use cutlass::*;
21
22pub fn cublas_scale_layout_kmajor() -> bool {
32 static KMAJOR: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
33 *KMAJOR.get_or_init(|| {
34 !matches!(
35 std::env::var("METRALE_CUBLAS_SCALE_LAYOUT").as_deref(),
36 Ok("rowmajor")
37 )
38 })
39}
40
41pub fn fp8_act_scale_to_kmajor(
48 gpu: &dyn metrale_gpu_runtime::gpu::GpuBackend,
49 kernel: metrale_gpu_runtime::gpu::KernelHandle,
50 a_scale: metrale_gpu_runtime::gpu::DevicePtr,
51 a_scale_kmajor: metrale_gpu_runtime::gpu::DevicePtr,
52 m: u32,
53 m_pad: u32,
54 k: u32,
55 stream: u64,
56) -> anyhow::Result<()> {
57 use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
58 let l = k / 128;
59 KernelLaunch::new(gpu, kernel)
60 .grid([div_ceil(m_pad, 256), l, 1])
61 .block([256, 1, 1])
62 .arg_ptr(a_scale)
63 .arg_ptr(a_scale_kmajor)
64 .arg_u32(m)
65 .arg_u32(m_pad)
66 .arg_u32(l)
67 .launch(stream)
68}
69
70#[allow(clippy::too_many_arguments)]
78pub fn cublas_fp8_proj(
79 gpu: &dyn metrale_gpu_runtime::gpu::GpuBackend,
80 ptg_quant_k: Fp8ActQuant,
81 scale_kmajor_k: metrale_gpu_runtime::gpu::KernelHandle,
82 act_bf16: metrale_gpu_runtime::gpu::DevicePtr,
83 act_fp8_scratch: metrale_gpu_runtime::gpu::DevicePtr,
84 act_scale_scratch: metrale_gpu_runtime::gpu::DevicePtr,
85 act_scale_kmajor_scratch: metrale_gpu_runtime::gpu::DevicePtr,
86 fp8w: &crate::weight_map::Fp8Weight,
87 out: metrale_gpu_runtime::gpu::DevicePtr,
88 m: u32,
89 n: u32,
90 k: u32,
91 stream: u64,
92) -> anyhow::Result<()> {
93 per_token_group_quant_fp8(
94 gpu,
95 ptg_quant_k,
96 act_bf16,
97 act_fp8_scratch,
98 act_scale_scratch,
99 m,
100 k,
101 stream,
102 )?;
103 cublas_fp8_proj_prequant(
104 gpu,
105 scale_kmajor_k,
106 act_fp8_scratch,
107 act_scale_scratch,
108 act_scale_kmajor_scratch,
109 fp8w,
110 out,
111 m,
112 n,
113 k,
114 stream,
115 )
116}
117
118#[allow(clippy::too_many_arguments)]
134pub fn cublas_fp8_proj_prequant(
135 gpu: &dyn metrale_gpu_runtime::gpu::GpuBackend,
136 scale_kmajor_k: metrale_gpu_runtime::gpu::KernelHandle,
137 act_fp8: metrale_gpu_runtime::gpu::DevicePtr,
138 act_scale: metrale_gpu_runtime::gpu::DevicePtr,
139 act_scale_kmajor: metrale_gpu_runtime::gpu::DevicePtr,
140 fp8w: &crate::weight_map::Fp8Weight,
141 out: metrale_gpu_runtime::gpu::DevicePtr,
142 m: u32,
143 n: u32,
144 k: u32,
145 stream: u64,
146) -> anyhow::Result<()> {
147 let m_pad = cublas_fp8_m_pad(m);
148 let kg = (k / 128) as usize;
149 if m_pad > m {
150 gpu.memset_async(
153 act_fp8.offset(m as usize * k as usize),
154 0,
155 (m_pad - m) as usize * k as usize,
156 stream,
157 )?;
158 }
159 let b_scale = if cublas_scale_layout_kmajor() {
160 if scale_kmajor_k.0 == 0 || act_scale_kmajor.0 == 0 {
161 anyhow::bail!(
162 "cuBLASLt block-scaled FP8 needs the fp8_act_scale_to_kmajor adapter \
163 (kernel={:#x}, scratch={:#x}) — see cublas_scale_layout_kmajor()",
164 scale_kmajor_k.0,
165 act_scale_kmajor.0
166 );
167 }
168 fp8_act_scale_to_kmajor(
171 gpu,
172 scale_kmajor_k,
173 act_scale,
174 act_scale_kmajor,
175 m,
176 m_pad,
177 k,
178 stream,
179 )?;
180 act_scale_kmajor
181 } else {
182 if m_pad > m {
185 gpu.memset_async(
186 act_scale.offset(m as usize * kg * 4),
187 0,
188 (m_pad - m) as usize * kg * 4,
189 stream,
190 )?;
191 }
192 act_scale
193 };
194 metrale_gpu_runtime::cublaslt::fp8_gemm_act_weight_t_blkscaled(
195 act_fp8.0,
196 b_scale.0,
197 fp8w.weight.0,
198 fp8w.row_scale.0,
199 out.0,
200 m_pad,
201 n,
202 k,
203 stream,
204 )
205}
206
207pub fn cublas_fp8_m_pad(m: u32) -> u32 {
210 m.div_ceil(16) * 16
211}
212
213pub fn dequant_fp8_bf16_into(
222 gpu: &dyn metrale_gpu_runtime::gpu::GpuBackend,
223 fp8w: &crate::weight_map::Fp8Weight,
224 dst: metrale_gpu_runtime::gpu::DevicePtr,
225 stream: u64,
226) -> anyhow::Result<()> {
227 use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
228 let (n, kk) = (fp8w.n, fp8w.k);
229 let per_row = fp8w.scale_format == crate::weight_map::WeightQuantFormat::Fp8PerRow;
230 let (block_n, block_k, sk) = if per_row {
231 (1u32, kk, 1u32)
232 } else {
233 (128u32, 128u32, kk / 128)
234 };
235 let kernel = gpu.kernel(
236 "dequant_fp8_blockscaled_bf16",
237 "dequant_fp8_blockscaled_bf16",
238 )?;
239 KernelLaunch::new(gpu, kernel)
240 .grid([div_ceil(kk, 64), div_ceil(n, 4), 1])
241 .block([64, 4, 1])
242 .arg_ptr(fp8w.weight)
243 .arg_ptr(fp8w.row_scale)
244 .arg_ptr(dst)
245 .arg_u32(n)
246 .arg_u32(kk)
247 .arg_u32(block_n)
248 .arg_u32(block_k)
249 .arg_u32(sk)
250 .arg_u32(1)
251 .launch(stream)
252}
253
254pub fn dequant_fp8_bf16_bytes(fp8w: &crate::weight_map::Fp8Weight) -> usize {
256 fp8w.n as usize * fp8w.k as usize * 2
257}
258
259pub fn cublas_bf16_proj_dense(
262 act: metrale_gpu_runtime::gpu::DevicePtr,
263 weight_bf16: metrale_gpu_runtime::gpu::DevicePtr,
264 out: metrale_gpu_runtime::gpu::DevicePtr,
265 m: u32,
266 n: u32,
267 k: u32,
268 stream: u64,
269) -> anyhow::Result<()> {
270 metrale_gpu_runtime::cublaslt::bf16_gemm_act_weight_t(
271 act.0,
272 weight_bf16.0,
273 out.0,
274 m,
275 n,
276 k,
277 stream,
278 )
279}
280
281pub fn cublas_bf16_proj_dense_f32_out(
284 act: metrale_gpu_runtime::gpu::DevicePtr,
285 weight_bf16: metrale_gpu_runtime::gpu::DevicePtr,
286 out: metrale_gpu_runtime::gpu::DevicePtr,
287 m: u32,
288 n: u32,
289 k: u32,
290 stream: u64,
291) -> anyhow::Result<()> {
292 metrale_gpu_runtime::cublaslt::bf16_gemm_act_weight_t_f32_out(
293 act.0,
294 weight_bf16.0,
295 out.0,
296 m,
297 n,
298 k,
299 stream,
300 )
301}