1#![allow(unused_imports)]
8
9use super::*;
10
11#[allow(clippy::too_many_arguments)]
20pub fn cublas_fp8_proj(
21 gpu: &dyn spark_runtime::gpu::GpuBackend,
22 ptg_quant_k: spark_runtime::gpu::KernelHandle,
23 act_bf16: spark_runtime::gpu::DevicePtr,
24 act_fp8_scratch: spark_runtime::gpu::DevicePtr,
25 act_scale_scratch: spark_runtime::gpu::DevicePtr,
26 fp8w: &crate::weight_map::Fp8Weight,
27 out: spark_runtime::gpu::DevicePtr,
28 m: u32,
29 n: u32,
30 k: u32,
31 stream: u64,
32) -> anyhow::Result<()> {
33 per_token_group_quant_fp8(
35 gpu,
36 ptg_quant_k,
37 act_bf16,
38 act_fp8_scratch,
39 act_scale_scratch,
40 m,
41 k,
42 stream,
43 )?;
44 let m_pad = m.div_ceil(16) * 16;
48 if m_pad > m {
49 let kg = (k / 128) as usize;
50 let pad_off = m as usize * kg * 4;
51 let pad_bytes = (m_pad - m) as usize * kg * 4;
52 gpu.memset_async(act_scale_scratch.offset(pad_off), 0, pad_bytes, stream)?;
53 }
54 spark_runtime::cublaslt::fp8_gemm_act_weight_t_blkscaled(
55 act_fp8_scratch.0,
56 act_scale_scratch.0,
57 fp8w.weight.0,
58 fp8w.row_scale.0,
59 out.0,
60 m_pad,
61 n,
62 k,
63 stream,
64 )
65}
66
67fn dequant_fp8_bf16_cached(
71 gpu: &dyn spark_runtime::gpu::GpuBackend,
72 derived: &super::DerivedWeights,
73 fp8w: &crate::weight_map::Fp8Weight,
74 stream: u64,
75) -> anyhow::Result<u64> {
76 use spark_runtime::kernel_args::{KernelLaunch, div_ceil};
77 let cache_key = fp8w.weight.0;
78 if let Some(hit) = derived.get_ptr(super::Derivation::Bf16, cache_key) {
79 return Ok(hit);
80 }
81 let (n, kk) = (fp8w.n, fp8w.k);
82 let out = gpu.alloc(n as usize * kk as usize * 2)?; let per_row = fp8w.scale_format == crate::weight_map::WeightQuantFormat::Fp8PerRow;
96 let (block_n, block_k, sk) = if per_row {
97 (1u32, kk, 1u32)
98 } else {
99 (128u32, 128u32, kk / 128)
100 };
101 let kernel = gpu.kernel(
102 "dequant_fp8_blockscaled_bf16",
103 "dequant_fp8_blockscaled_bf16",
104 )?;
105 KernelLaunch::new(gpu, kernel)
106 .grid([div_ceil(kk, 64), div_ceil(n, 4), 1])
107 .block([64, 4, 1])
108 .arg_ptr(fp8w.weight)
109 .arg_ptr(fp8w.row_scale)
110 .arg_ptr(out)
111 .arg_u32(n)
112 .arg_u32(kk)
113 .arg_u32(block_n)
114 .arg_u32(block_k)
115 .arg_u32(sk)
116 .arg_u32(1) .launch(stream)?;
118 derived.insert_ptr(super::Derivation::Bf16, cache_key, out.0);
119 Ok(out.0)
120}
121
122fn dequant_fp8_bf16_uncached(
123 gpu: &dyn spark_runtime::gpu::GpuBackend,
124 fp8w: &crate::weight_map::Fp8Weight,
125 stream: u64,
126) -> anyhow::Result<spark_runtime::gpu::DevicePtr> {
127 use spark_runtime::kernel_args::{KernelLaunch, div_ceil};
128 let (n, kk) = (fp8w.n, fp8w.k);
129 let out = gpu.alloc(n as usize * kk as usize * 2)?;
130 let block = 128u32;
131 let sk = kk / block;
132 let kernel = gpu.kernel(
133 "dequant_fp8_blockscaled_bf16",
134 "dequant_fp8_blockscaled_bf16",
135 )?;
136 KernelLaunch::new(gpu, kernel)
137 .grid([div_ceil(kk, 64), div_ceil(n, 4), 1])
138 .block([64, 4, 1])
139 .arg_ptr(fp8w.weight)
140 .arg_ptr(fp8w.row_scale)
141 .arg_ptr(out)
142 .arg_u32(n)
143 .arg_u32(kk)
144 .arg_u32(block)
145 .arg_u32(block)
146 .arg_u32(sk)
147 .arg_u32(1)
148 .launch(stream)?;
149 Ok(out)
150}
151
152#[allow(clippy::too_many_arguments)]
156pub fn cublas_bf16_proj(
157 gpu: &dyn spark_runtime::gpu::GpuBackend,
158 derived: &super::DerivedWeights,
159 act: spark_runtime::gpu::DevicePtr,
160 fp8w: &crate::weight_map::Fp8Weight,
161 out: spark_runtime::gpu::DevicePtr,
162 m: u32,
163 n: u32,
164 k: u32,
165 stream: u64,
166) -> anyhow::Result<()> {
167 let w_bf16 = dequant_fp8_bf16_cached(gpu, derived, fp8w, stream)?;
168 spark_runtime::cublaslt::bf16_gemm_act_weight_t(act.0, w_bf16, out.0, m, n, k, stream)
169}
170
171pub fn cublas_bf16_proj_dense(
176 act: spark_runtime::gpu::DevicePtr,
177 weight_bf16: spark_runtime::gpu::DevicePtr,
178 out: spark_runtime::gpu::DevicePtr,
179 m: u32,
180 n: u32,
181 k: u32,
182 stream: u64,
183) -> anyhow::Result<()> {
184 spark_runtime::cublaslt::bf16_gemm_act_weight_t(act.0, weight_bf16.0, out.0, m, n, k, stream)
185}
186
187#[allow(clippy::too_many_arguments)]
196pub fn cutlass_bf16_proj(
197 gpu: &dyn spark_runtime::gpu::GpuBackend,
198 derived: &super::DerivedWeights,
199 act: spark_runtime::gpu::DevicePtr,
200 fp8w: &crate::weight_map::Fp8Weight,
201 out: spark_runtime::gpu::DevicePtr,
202 m: u32,
203 n: u32,
204 k: u32,
205 stream: u64,
206) -> anyhow::Result<()> {
207 let w_bf16 = dequant_fp8_bf16_cached(gpu, derived, fp8w, stream)?;
208 spark_runtime::cutlass::bf16_gemm_act_weight_t(act.0, w_bf16, out.0, m, n, k, stream)
209}
210
211#[allow(clippy::too_many_arguments)]
216fn cutlass_nvfp4_weight_transposed_cached(
221 gpu: &dyn spark_runtime::gpu::GpuBackend,
222 derived: &super::DerivedWeights,
223 weight_t: &crate::weight_map::QuantizedWeight,
224 n: u32,
225 k: u32,
226 stream: u64,
227) -> anyhow::Result<u64> {
228 let cache_key = weight_t.weight.0;
229 if let Some(hit) = derived.get_ptr(super::Derivation::CutlassNvfp4Transposed, cache_key) {
230 return Ok(hit);
231 }
232 let dst = gpu.alloc((n as usize) * (k as usize) / 2)?;
233 spark_runtime::cutlass::transpose_nvfp4_packed_kton(weight_t.weight.0, dst.0, n, k, stream)?;
234 gpu.synchronize(stream)?;
235 derived.insert_ptr(super::Derivation::CutlassNvfp4Transposed, cache_key, dst.0);
236 Ok(dst.0)
237}
238
239#[allow(clippy::too_many_arguments)]
240pub fn cutlass_nvfp4_proj(
241 ctx: &crate::layer::ForwardContext<'_>,
245 act: spark_runtime::gpu::DevicePtr,
246 weight_t: &crate::weight_map::QuantizedWeight,
247 out: spark_runtime::gpu::DevicePtr,
248 m: u32,
249 n: u32,
250 k: u32,
251 stream: u64,
252) -> anyhow::Result<()> {
253 let (gpu, derived) = (ctx.gpu, ctx.derived);
254 let packed = cutlass_nvfp4_weight_transposed_cached(gpu, derived, weight_t, n, k, stream)?;
255 spark_runtime::cutlass::nvfp4_gemm_bf16_act_weight_t(
256 act.0,
257 packed,
258 weight_t.weight_scale.0,
259 weight_t.weight_scale_2,
260 out.0,
261 m,
262 n,
263 k,
264 stream,
265 )
266}
267
268fn cutlass_nvfp4_weight_from_fp8_cached(
269 gpu: &dyn spark_runtime::gpu::GpuBackend,
270 derived: &super::DerivedWeights,
271 fp8w: &crate::weight_map::Fp8Weight,
272 stream: u64,
273) -> anyhow::Result<(u64, u64)> {
274 let cache_key = fp8w.weight.0;
275 if let Some(hit) = derived.get_pair(super::Derivation::CutlassNvfp4FromFp8, cache_key) {
276 return Ok(hit);
277 }
278
279 let n = fp8w.n as usize;
280 let k = fp8w.k as usize;
281 let w_bf16 = dequant_fp8_bf16_uncached(gpu, fp8w, stream)?;
282 let packed_t = gpu.alloc(n * k / 2)?;
283 let scale_t = gpu.alloc(n * k / 16)?;
284 spark_runtime::cutlass::pack_bf16_weight_to_nvfp4_t(
285 w_bf16.0, packed_t.0, scale_t.0, fp8w.n, fp8w.k, stream,
286 )?;
287 gpu.synchronize(stream)?;
288 gpu.free(w_bf16)?;
289 derived.insert_pair(
290 super::Derivation::CutlassNvfp4FromFp8,
291 cache_key,
292 (packed_t.0, scale_t.0),
293 );
294 Ok((packed_t.0, scale_t.0))
295}
296
297#[allow(clippy::too_many_arguments)]
301pub fn cutlass_nvfp4_proj_from_fp8(
302 ctx: &crate::layer::ForwardContext<'_>,
306 act: spark_runtime::gpu::DevicePtr,
307 fp8w: &crate::weight_map::Fp8Weight,
308 out: spark_runtime::gpu::DevicePtr,
309 m: u32,
310 n: u32,
311 k: u32,
312 stream: u64,
313) -> anyhow::Result<()> {
314 let (gpu, derived) = (ctx.gpu, ctx.derived);
315 let (packed_t, scale_t) = cutlass_nvfp4_weight_from_fp8_cached(gpu, derived, fp8w, stream)?;
316 spark_runtime::cutlass::nvfp4_gemm_bf16_act_weight_t(
317 act.0, packed_t, scale_t, 1.0, out.0, m, n, k, stream,
318 )
319}