(w, n_bit=8,
zero_point=True, q_group_size=-1,
inplace=False,
get_scale_zp=False
)
| 17 | |
| 18 | # core quantization method (simulated quantization) |
| 19 | def pseudo_quantize_tensor(w, n_bit=8, |
| 20 | zero_point=True, q_group_size=-1, |
| 21 | inplace=False, |
| 22 | get_scale_zp=False |
| 23 | ): |
| 24 | org_w_shape = w.shape |
| 25 | if q_group_size > 0: |
| 26 | assert org_w_shape[-1] % q_group_size == 0 |
| 27 | w = w.reshape(-1, q_group_size) |
| 28 | elif q_group_size == -1: |
| 29 | w = w.reshape(-1, w.shape[-1]) |
| 30 | assert w.dim() == 2 |
| 31 | if zero_point: |
| 32 | max_val = w.amax(dim=1, keepdim=True) |
| 33 | min_val = w.amin(dim=1, keepdim=True) |
| 34 | max_int = 2 ** n_bit - 1 |
| 35 | min_int = 0 |
| 36 | scales = (max_val - min_val).clamp(min=1e-5) / max_int |
| 37 | zeros = (-torch.round(min_val / scales)).clamp_(min_int, max_int) |
| 38 | else: # we actually never used this |
| 39 | assert min_val is None |
| 40 | max_val = w.abs().amax(dim=1, keepdim=True) |
| 41 | max_val = max_val.clamp(min=1e-5) |
| 42 | max_int = 2 ** (n_bit - 1) - 1 |
| 43 | min_int = - 2 ** (n_bit - 1) |
| 44 | scales = max_val / max_int |
| 45 | zeros = 0 |
| 46 | |
| 47 | assert torch.isnan(scales).sum() == 0 |
| 48 | assert torch.isnan(w).sum() == 0 |
| 49 | |
| 50 | if inplace: |
| 51 | ((w.div_(scales).round_().add_(zeros)).clamp_( |
| 52 | min_int, max_int).sub_(zeros)).mul_(scales) |
| 53 | else: |
| 54 | w = (torch.clamp(torch.round(w / scales) + |
| 55 | zeros, min_int, max_int) - zeros) * scales |
| 56 | assert torch.isnan(w).sum() == 0 |
| 57 | |
| 58 | w = w.reshape(org_w_shape) |
| 59 | |
| 60 | if get_scale_zp: |
| 61 | return w, scales.view(w.shape[0], -1), zeros.view(w.shape[0], -1) |
| 62 | else: |
| 63 | return w |
| 64 | |
| 65 | @torch.no_grad() |
| 66 | def pseudo_quantize_model_weight( |
no outgoing calls
no test coverage detected