|
15 | 15 | from typing import Tuple |
16 | 16 |
|
17 | 17 | import torch |
| 18 | +import triton |
| 19 | +import triton.language as tl |
18 | 20 |
|
19 | 21 | from .metrics import mse_loss |
20 | 22 |
|
@@ -314,3 +316,67 @@ def tensor_quant_dequant_fp8(x, scale, bits=8, mantissa_bit=3, sign_bits=1): |
314 | 316 | ) |
315 | 317 | quant_dequant_x *= scale |
316 | 318 | return quant_dequant_x |
| 319 | + |
| 320 | + |
| 321 | +# This function is copied from DeepSeek-V3 (MIT License): |
| 322 | +# Copyright (c) 2023 DeepSeek-AI |
| 323 | +# Original source: https://github.com/deepseek-ai/DeepSeek-V3 |
| 324 | +@triton.jit |
| 325 | +def weight_dequant_kernel(x_ptr, s_ptr, y_ptr, M, N, BLOCK_SIZE: tl.constexpr): |
| 326 | + """ |
| 327 | + Dequantizes weights using the provided scaling factors and stores the result. |
| 328 | +
|
| 329 | + Args: |
| 330 | + x_ptr (tl.pointer): Pointer to the quantized weights. |
| 331 | + s_ptr (tl.pointer): Pointer to the scaling factors. |
| 332 | + y_ptr (tl.pointer): Pointer to the output buffer for dequantized weights. |
| 333 | + M (int): Number of rows in the weight matrix. |
| 334 | + N (int): Number of columns in the weight matrix. |
| 335 | + BLOCK_SIZE (tl.constexpr): Size of the block for tiling. |
| 336 | +
|
| 337 | + Returns: |
| 338 | + None |
| 339 | + """ |
| 340 | + pid_m = tl.program_id(axis=0) |
| 341 | + pid_n = tl.program_id(axis=1) |
| 342 | + n = tl.cdiv(N, BLOCK_SIZE) |
| 343 | + offs_m = pid_m * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) |
| 344 | + offs_n = pid_n * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) |
| 345 | + offs = offs_m[:, None] * N + offs_n[None, :] |
| 346 | + mask = (offs_m[:, None] < M) & (offs_n[None, :] < N) |
| 347 | + x = tl.load(x_ptr + offs, mask=mask).to(tl.float32) |
| 348 | + s = tl.load(s_ptr + pid_m * n + pid_n) |
| 349 | + y = x * s |
| 350 | + tl.store(y_ptr + offs, y, mask=mask) |
| 351 | + |
| 352 | + |
| 353 | +# This function is copied from DeepSeek-V3 (MIT License): |
| 354 | +# Copyright (c) 2023 DeepSeek-AI |
| 355 | +# Original source: https://github.com/deepseek-ai/DeepSeek-V3 |
| 356 | +def weight_dequant( |
| 357 | + x: torch.Tensor, s: torch.Tensor, block_size: int = 128 |
| 358 | +) -> torch.Tensor: |
| 359 | + """ |
| 360 | + Dequantizes the given weight tensor using the provided scale tensor. |
| 361 | +
|
| 362 | + Args: |
| 363 | + x (torch.Tensor): The quantized weight tensor of shape (M, N). |
| 364 | + s (torch.Tensor): The scale tensor of shape (M, N). |
| 365 | + block_size (int, optional): The block size to use for dequantization. Defaults to 128. # noqa: E501 |
| 366 | +
|
| 367 | + Returns: |
| 368 | + torch.Tensor: The dequantized weight tensor of the same shape as `x`. |
| 369 | +
|
| 370 | + Raises: |
| 371 | + AssertionError: If `x` or `s` are not contiguous or if their dimensions are not 2. # noqa: E501 |
| 372 | + """ |
| 373 | + assert x.is_contiguous() and s.is_contiguous(), "Input tensors must be contiguous" |
| 374 | + assert x.dim() == 2 and s.dim() == 2, "Input tensors must have 2 dimensions" |
| 375 | + M, N = x.size() |
| 376 | + y = torch.empty_like(x, dtype=torch.get_default_dtype()) |
| 377 | + grid = lambda meta: ( # noqa: E731 |
| 378 | + triton.cdiv(M, meta["BLOCK_SIZE"]), |
| 379 | + triton.cdiv(N, meta["BLOCK_SIZE"]), |
| 380 | + ) |
| 381 | + weight_dequant_kernel[grid](x, s, y, M, N, BLOCK_SIZE=block_size) |
| 382 | + return y |
0 commit comments