已合并
deprecate LinearA8W8quant #17110
lifei265创建于 2024年12月28日
deprecate LinearA8W8quant #17110
已合并
从refs/pull/17110/head合入到master
共 2 个文件变更+42-1
| @@ -47,7 +47,8 @@ class TestLinearA8W8Quant(TestCase): | |||
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | "OP `QuantBatchMatmulV3` is not supported on 910A or 310P, skip this ut for this device type!") | 49 | "OP `QuantBatchMatmulV3` is not supported on 910A or 310P, skip this ut for this device type!") |
| 50 | - def test_npu_linear_quant_out_int32(self): | 50 | + @unittest.expectedFailure |
| 51 | + def test_npu_linear_quant_out_int32_error(self): | ||
| 51 | x1 = torch.randint(-1, 1, (1, 5), dtype=torch.int8).npu() | 52 | x1 = torch.randint(-1, 1, (1, 5), dtype=torch.int8).npu() |
| 52 | x2 = torch.randint(-1, 1, (127, 5), dtype=torch.int8).npu() | 53 | x2 = torch.randint(-1, 1, (127, 5), dtype=torch.int8).npu() |
| 53 | scale = torch.randn(1, dtype=torch.float32).npu() | 54 | scale = torch.randn(1, dtype=torch.float32).npu() |
| @@ -61,5 +62,22 @@ class TestLinearA8W8Quant(TestCase): | |||
| 61 | npu_out = model(x1) | 62 | npu_out = model(x1) |
| 62 | self.assertRtolEqual(supported_output, npu_out, 0.001) | 63 | self.assertRtolEqual(supported_output, npu_out, 0.001) |
| 63 | 64 | ||
| 65 | + | ||
| 66 | + "OP `QuantBatchMatmulV3` is not supported on 910A or 310P, skip this ut for this device type!") | ||
| 67 | + | ||
| 68 | + def test_npu_linear_quant_scale_fp16_error(self): | ||
| 69 | + x1 = torch.randint(-1, 1, (1, 5), dtype=torch.int8).npu() | ||
| 70 | + x2 = torch.randint(-1, 1, (127, 5), dtype=torch.int8).npu() | ||
| 71 | + scale = torch.randn(1, dtype=torch.float16).npu() | ||
| 72 | + out_dtype = torch.int8 | ||
| 73 | + supported_output = torch_npu.npu_quant_matmul(x1, x2.t(), scale, output_dtype=out_dtype) | ||
| 74 | + in_features = 5 | ||
| 75 | + out_features = 127 | ||
| 76 | + model = LinearA8W8Quant(in_features, out_features, bias=False, offset=False, pertoken_scale=False, output_dtype=out_dtype) | ||
| 77 | + model.weight.data = x2 | ||
| 78 | + model.scale.data = scale | ||
| 79 | + npu_out = model(x1) | ||
| 80 | + self.assertRtolEqual(supported_output, npu_out, 0.001) | ||
| 81 | + | ||
| 64 | if __name__ == "__main__": | 82 | if __name__ == "__main__": |
| 65 | run_tests() | 83 | run_tests() |
| @@ -1,8 +1,10 @@ | |||
| 1 | +import warnings | ||
| 1 | import torch | 2 | import torch |
| 2 | import torch.nn as nn | 3 | import torch.nn as nn |
| 3 | from torch import Tensor | 4 | from torch import Tensor |
| 4 | from torch.nn.parameter import Parameter | 5 | from torch.nn.parameter import Parameter |
| 5 | import torch_npu | 6 | import torch_npu |
| 7 | +from torch_npu.utils._error_code import ErrCode, ops_error | ||
| 6 | 8 | ||
| 7 | __all__ = ["LinearA8W8Quant"] | 9 | __all__ = ["LinearA8W8Quant"] |
| 8 | 10 | ||
| @@ -60,6 +62,8 @@ class LinearA8W8Quant(nn.Module): | |||
| 60 | pertoken_scale: bool = False, device=None, dtype=None, output_dtype=None) -> None: | 62 | pertoken_scale: bool = False, device=None, dtype=None, output_dtype=None) -> None: |
| 61 | 63 | ||
| 62 | super(LinearA8W8Quant, self).__init__() | 64 | super(LinearA8W8Quant, self).__init__() |
| 65 | + warnings.warn("torch_npu.contrib.module.LinearA8W8Quant is deprecated and will be removed in future version. " | ||
| 66 | + "Use torch_npu.contrib.module.LinearQuant instead.", FutureWarning) | ||
| 63 | self.in_features = in_features | 67 | self.in_features = in_features |
| 64 | self.out_features = out_features | 68 | self.out_features = out_features |
| 65 | self.weight = Parameter(torch.empty((out_features, in_features)), False) | 69 | self.weight = Parameter(torch.empty((out_features, in_features)), False) |
| @@ -84,6 +88,25 @@ class LinearA8W8Quant(nn.Module): | |||
| 84 | scale_quant = self.scale | 88 | scale_quant = self.scale |
| 85 | first_last_dim = self.weight.dim() - 1 | 89 | first_last_dim = self.weight.dim() - 1 |
| 86 | second_last_dim = self.weight.dim() - 2 | 90 | second_last_dim = self.weight.dim() - 2 |
| 91 | + if not ((linear_quant_input.dtype == torch.int32 and self.weight.dtype == torch.int32) or | ||
| 92 | + (linear_quant_input.dtype == torch.int8 and self.weight.dtype == torch.int8)): | ||
| 93 | + raise ValueError("input and weight should be both torch.int32 or both torch.int8 datatype, " | ||
| 94 | + f"but now input is {linear_quant_input.dtype}, weight is {self.weight.dtype}." + ops_error(ErrCode.TYPE)) | ||
| 95 | + if self.scale.dtype not in [torch.int64, torch.float32, torch.bfloat16]: | ||
| 96 | + raise ValueError("scale should be torch.int64, torch.float32 or torch.bfloat16 datatype, " | ||
| 97 | + f"but now it is {self.scale.dtype}." + ops_error(ErrCode.TYPE)) | ||
| 98 | + if self.offset is not None and self.offset.dtype is not torch.float32: | ||
| 99 | + raise ValueError("offset should be torch.float32 datatype, " | ||
| 100 | + f"but now it is {self.offset.dtype}." + ops_error(ErrCode.TYPE)) | ||
| 101 | + if self.bias is not None and self.bias.dtype not in [torch.int32, torch.bfloat16, torch.float16, torch.float32]: | ||
| 102 | + raise ValueError("bias should be torch.int32, torch.bfloat16, torch.float16 or torch.float32 datatype, " | ||
| 103 | + f"but now it is {self.bias.dtype}." + ops_error(ErrCode.TYPE)) | ||
| 104 | + if self.pertoken_scale is not None and self.pertoken_scale.dtype is not torch.float32: | ||
| 105 | + raise ValueError("pertoken_scale should be torch.float32 datatype, " | ||
| 106 | + f"but now it is {self.pertoken_scale.dtype}." + ops_error(ErrCode.TYPE)) | ||
| 107 | + if self.output_dtype is not None and self.output_dtype not in [torch.int8, torch.float16, torch.bfloat16]: | ||
| 108 | + raise ValueError("output_dtype should be torch.int8, torch.float16 or torch.bfloat16, " | ||
| 109 | + f"but now it is {self.output_dtype}." + ops_error(ErrCode.TYPE)) | ||
| 87 | is_check_dtype_ok = (self.scale.dtype == torch.float32 and | 110 | is_check_dtype_ok = (self.scale.dtype == torch.float32 and |
| 88 | self.output_dtype not in [torch.bfloat16, torch.int32]) | 111 | self.output_dtype not in [torch.bfloat16, torch.int32]) |
| 89 | if self.pertoken_scale is None and is_check_dtype_ok: | 112 | if self.pertoken_scale is None and is_check_dtype_ok: |