Dequantize a 2-D FP8 weight tensor using its per-block scale factor.
(weight: &Tensor, scale_inv: &Tensor)
| 41 | |
| 42 | /// Dequantize a 2-D FP8 weight tensor using its per-block scale factor. |
| 43 | pub fn dequantize_fp8_blockwise(weight: &Tensor, scale_inv: &Tensor) -> candle_core::Result<Tensor> { |
| 44 | let (m, n) = weight.dims2()?; |
| 45 | let bm = FP8_BLOCK_SIZE; |
| 46 | let bn = FP8_BLOCK_SIZE; |
| 47 | let blocks_m = m.div_ceil(bm); |
| 48 | let blocks_n = n.div_ceil(bn); |
| 49 | |
| 50 | // Cast FP8 → F32 on CPU (candle supports this on CPU) |
| 51 | let weight_f32 = weight.to_dtype(DType::F32)?; |
| 52 | let scale_f32 = scale_inv.to_dtype(DType::F32)?; |
| 53 | |
| 54 | // Reshape for block-wise broadcast multiply: |
| 55 | // weight: [M, N] → [blocks_m, bm, blocks_n, bn] |
| 56 | // scale: [blocks_m, blocks_n] → [blocks_m, 1, blocks_n, 1] |
| 57 | let weight_blocked = weight_f32.reshape((blocks_m, bm, blocks_n, bn))?; |
| 58 | let scale_blocked = scale_f32.reshape((blocks_m, 1usize, blocks_n, 1usize))?; |
| 59 | |
| 60 | let dequantized = weight_blocked.broadcast_mul(&scale_blocked)?; |
| 61 | dequantized.reshape((m, n)) |
| 62 | } |
| 63 | |
| 64 | /// Custom VarBuilder backend that wraps MmapedSafetensors and transparently |
| 65 | /// dequantizes FP8-quantized weight tensors on CPU before moving to the target device. |
no outgoing calls