//  [python]
def fasterquant(
        self,
        blocksize=128,  # 和groupsize需要对齐吗?
        percdamp=0.01,
        enable_svd_deltaW=False,
        svd_deltaW_rank=8,
        enable_gscales_decompose=False,
        quant_type="gptq",
    ):
        w_dtype = self.layer.weight.data.dtype
        weight = self.layer.weight.data.clone().float()
        H = self.Hessian
        dead_idx = torch.diag(H) == 0
        H[dead_idx, dead_idx] = 1
        weight[:, dead_idx] = 0
        # apply dampening to avoid numerical issues, but only work for a model with few billion paprameters
        damp = percdamp * torch.mean(torch.diag(H))
        diag = torch.arange(self.columns, device=self.device)
        H[diag, diag] += damp
        # use Cholesky to speedup & avoid numerical issues further in large models
        H = torch.linalg.cholesky(H)
        H = torch.cholesky_inverse(H)
        H = torch.linalg.cholesky(H, upper=True)
        Hinv = H
        if quant_type == "rtn":
            if not self.is_ready:
                self.calc_qparams(weight)
            fq_weight = self.fake_quantize(
                weight.reshape(self.out_features, self.groups, -1)
            ).reshape(weight.shape)
            if enable_svd_deltaW:
                print("svd deltaW rank : {}".format(svd_deltaW_rank))
                delta_w = self.layer.weight.data - fq_weight
                w_weights = torch.diag(Hinv)[None, :]
                delta_w_weighted = delta_w / w_weights
                U, S, Vh = torch.linalg.svd(delta_w_weighted.float())
                svd_deltaW_B = (
                    U[:, 0:svd_deltaW_rank]
                    @ torch.diag(S)[0:svd_deltaW_rank, 0:svd_deltaW_rank]
                ).to(w_dtype)
                svd_deltaW_A = (Vh[0:svd_deltaW_rank, :] * w_weights).to(w_dtype)
            else:
                svd_deltaW_A = svd_deltaW_B = None

            self.layer.weight.data = fq_weight.to(w_dtype)

            if enable_gscales_decompose:
                self.decompose_group_scales()
                self.scales = self.base_scales + self.step_scales * self.qstep
                self.enable_gscales_decompose = True
            return (svd_deltaW_A, svd_deltaW_B)

        losses = torch.zeros_like(weight)
        fq_weight = torch.zeros_like(weight)
        scales_memory = torch.zeros(
            (self.out_features, self.groups, 1),
            dtype=torch.float16,
            device=weight.device,
        )
        zeros_memory = torch.zeros(
            (self.out_features, self.groups, 1),
            dtype=torch.float16,
            device=weight.device,
        )
        if self.groupsize != -1:
            blocksize = self.groupsize  # override blocksize
        for start_i in range(
            0, self.columns, blocksize
        ):  # loop in ic dim by blocksize step
            end_i = min(start_i + blocksize, self.columns)
            if self.groupsize != -1 and (end_i - start_i) % self.groupsize == 0:
                # calc quant params in a group
                self.calc_qparams(weight[:, start_i:end_i], groupsize=self.groupsize)
                scales_memory[:, start_i // self.groupsize, 0] = self.scales.squeeze()
                zeros_memory[:, start_i // self.groupsize, 0] = self.zeros.squeeze()
            elif not self.is_ready:
                self.calc_qparams(weight)
                scales_memory = self.scales.clone()
                zeross_memory = self.zeros.clone()
            # init block vars
            block_weight = weight[:, start_i:end_i].clone()
            block_fq_weight = torch.zeros_like(block_weight)
            block_err = torch.zeros_like(block_weight)
            block_losses = torch.zeros_like(block_weight)
            block_Hinv = Hinv[start_i:end_i, start_i:end_i]
            for j in range(end_i - start_i):  # loop every column in a block
                col_weight = block_weight[:, j]
                diag_val = block_Hinv[j, j]
                col_fq_weight = self.fake_quantize(
                    col_weight[..., None, None].to(w_dtype)
                ).flatten()
                block_fq_weight[:, j] = col_fq_weight
                block_losses[:, j] = (
                    col_weight - col_fq_weight
                ) ** 2 / diag_val**2  # d^2 becuase cholesky, eq2-left
                col_err = (col_weight - col_fq_weight) / diag_val
                block_weight[:, j:] -= col_err.unsqueeze(1).matmul(
                    block_Hinv[j, j:].unsqueeze(0)
                )  # update remaining block weights
                block_err[:, j] = col_err
            fq_weight[:, start_i:end_i] = block_fq_weight
            losses[:, start_i:end_i] = block_losses / 2  # why div 2?
            # update the remaining parameters
            weight[:, end_i:] -= block_err.matmul(Hinv[start_i:end_i, end_i:])
        torch.cuda.synchronize()

        w_dtype = self.layer.weight.data.dtype
        fq_weight = fq_weight.to(w_dtype)
        self.scales, self.zeros = scales_memory, zeros_memory
        if enable_svd_deltaW:
            print("svd deltaW rank : {}".format(svd_deltaW_rank))
            delta_w = self.layer.weight.data - fq_weight
            w_weights = torch.diag(Hinv)[None, :]
            delta_w_weighted = delta_w / w_weights
            U, S, Vh = torch.linalg.svd(delta_w_weighted.float())
            svd_deltaW_B = (
                U[:, 0:svd_deltaW_rank]
                @ torch.diag(S)[0:svd_deltaW_rank, 0:svd_deltaW_rank]
            ).to(w_dtype)
            svd_deltaW_A = (Vh[0:svd_deltaW_rank, :] * w_weights).to(w_dtype)
        else:
            svd_deltaW_A = svd_deltaW_B = None

        self.layer.weight.data = fq_weight

        if enable_gscales_decompose:
            self.decompose_group_scales()
            self.scales = self.base_scales + self.step_scales * self.qstep
            self.enable_gscales_decompose = True

        return (svd_deltaW_A, svd_deltaW_B)