Upload 16 files
Browse files- config.py +1 -0
- cuda_backend.py +69 -58
- gguf.py +7 -1
- pipeline.py +26 -38
- seeds.py +20 -2
config.py
CHANGED
|
@@ -74,6 +74,7 @@ class HPCConfig:
|
|
| 74 |
clamp_kurtosis_soft: float = 20.0
|
| 75 |
clamp_sigma_soft: float = 6.0
|
| 76 |
clamp_sigma_hard: float = 4.0
|
|
|
|
| 77 |
|
| 78 |
# ---- reporting & parallelism ----------------------------------------
|
| 79 |
device: str = "auto"
|
|
|
|
| 74 |
clamp_kurtosis_soft: float = 20.0
|
| 75 |
clamp_sigma_soft: float = 6.0
|
| 76 |
clamp_sigma_hard: float = 4.0
|
| 77 |
+
temper_imatrix: bool = True
|
| 78 |
|
| 79 |
# ---- reporting & parallelism ----------------------------------------
|
| 80 |
device: str = "auto"
|
cuda_backend.py
CHANGED
|
@@ -223,10 +223,31 @@ def _make_qp_cuda(values: "torch.Tensor", weights: "torch.Tensor", nmax: int = 1
|
|
| 223 |
return d, codes.to(torch.uint8)
|
| 224 |
|
| 225 |
|
| 226 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
B = X.shape[0]
|
| 228 |
blocks = X.reshape(B, 16, 16)
|
| 229 |
-
|
|
|
|
| 230 |
if W is None:
|
| 231 |
sigma_sq = torch.mean(blocks * blocks, dim=(1, 2), keepdim=True)
|
| 232 |
weights = torch.sqrt(sigma_sq + clipped * clipped)
|
|
@@ -248,19 +269,19 @@ def _build_seeds_cuda(X: "torch.Tensor", W: "torch.Tensor | None", clamp_val: fl
|
|
| 248 |
"dmin": dmin,
|
| 249 |
"ls": ls,
|
| 250 |
"lm": lm,
|
|
|
|
| 251 |
}
|
| 252 |
|
| 253 |
|
| 254 |
-
def _phase2_wls_cuda(X: "torch.Tensor", W: "torch.Tensor", seeds: dict
|
| 255 |
-
|
|
|
|
| 256 |
base_d = seeds["d"].clone()
|
| 257 |
base_m = seeds["dmin"].clone()
|
| 258 |
ls = seeds["ls"].clone()
|
| 259 |
lm = seeds["lm"].clone()
|
| 260 |
scales = seeds["scales"]
|
| 261 |
mins = seeds["mins"]
|
| 262 |
-
seed_d = seeds["d"]
|
| 263 |
-
seed_m = seeds["dmin"]
|
| 264 |
|
| 265 |
for _ in range(5):
|
| 266 |
codes = _codes_from_params_t(clipped, base_d, base_m, ls, lm).to(torch.float32)
|
|
@@ -276,8 +297,8 @@ def _phase2_wls_cuda(X: "torch.Tensor", W: "torch.Tensor", seeds: dict, clamp_va
|
|
| 276 |
s_det = torch.where(valid, det, torch.ones_like(det))
|
| 277 |
d_new = (Sbb * Sxa - Sab * Sxb) / s_det
|
| 278 |
m_new = (Sab * Sxa - Saa * Sxb) / s_det
|
| 279 |
-
upd_d = valid & (d_new > 0.0) &
|
| 280 |
-
upd_m = valid & (m_new > 0.0) &
|
| 281 |
base_d = torch.where(upd_d, _round_fp16_t(d_new), base_d)
|
| 282 |
base_m = torch.where(upd_m, _round_fp16_t(m_new), base_m)
|
| 283 |
sd = torch.where(base_d > 1.0e-15, base_d, torch.ones_like(base_d))
|
|
@@ -584,10 +605,10 @@ def _standalone_coupled_solve_cuda(
|
|
| 584 |
d = _round_fp16_t(d)
|
| 585 |
m = _round_fp16_t(m)
|
| 586 |
codes = _codes_from_params_t(X, d, m, ls, lm)
|
| 587 |
-
|
| 588 |
-
take =
|
| 589 |
if torch.any(take):
|
| 590 |
-
best_obj = torch.where(take,
|
| 591 |
best_d = torch.where(take, d, best_d)
|
| 592 |
best_m = torch.where(take, m, best_m)
|
| 593 |
best_ls = torch.where(take[:, None], ls, best_ls)
|
|
@@ -617,29 +638,6 @@ def _extended_dm_solve_and_ulp_cuda(
|
|
| 617 |
Sxa = torch.sum(W * X * A, dim=1)
|
| 618 |
Sxb = torch.sum(W * X * Bm, dim=1)
|
| 619 |
|
| 620 |
-
if cfg.use_spectral:
|
| 621 |
-
if cfg.vw_lambda > 0.0:
|
| 622 |
-
vw_w = float(cfg.vw_lambda) / QK_K
|
| 623 |
-
half = QK_K // 2
|
| 624 |
-
Ap = A[:, :half] + A[:, half:]
|
| 625 |
-
Bp = Bm[:, :half] + Bm[:, half:]
|
| 626 |
-
Xp = X[:, :half] + X[:, half:]
|
| 627 |
-
Saa = Saa + vw_w * torch.sum(Ap * Ap, dim=1)
|
| 628 |
-
Sab = Sab + vw_w * torch.sum(Ap * Bp, dim=1)
|
| 629 |
-
Sbb = Sbb + vw_w * torch.sum(Bp * Bp, dim=1)
|
| 630 |
-
Sxa = Sxa + vw_w * torch.sum(Xp * Ap, dim=1)
|
| 631 |
-
Sxb = Sxb + vw_w * torch.sum(Xp * Bp, dim=1)
|
| 632 |
-
if cfg.dc_lambda > 0.0:
|
| 633 |
-
dc_w = float(cfg.dc_lambda) / QK_K
|
| 634 |
-
rA = torch.sum(A, dim=1)
|
| 635 |
-
rB = torch.sum(Bm, dim=1)
|
| 636 |
-
rS = torch.sum(X, dim=1) + carry
|
| 637 |
-
Saa = Saa + dc_w * rA * rA
|
| 638 |
-
Sab = Sab + dc_w * rA * rB
|
| 639 |
-
Sbb = Sbb + dc_w * rB * rB
|
| 640 |
-
Sxa = Sxa + dc_w * rS * rA
|
| 641 |
-
Sxb = Sxb + dc_w * rS * rB
|
| 642 |
-
|
| 643 |
det = Saa * Sbb - Sab * Sab
|
| 644 |
valid = det > 1.0e-30
|
| 645 |
s_det = torch.where(valid, det, torch.ones_like(det))
|
|
@@ -691,7 +689,7 @@ def _refine_trajectory_cuda(
|
|
| 691 |
best_d, best_m = d0.clone(), m0.clone()
|
| 692 |
best_ls, best_lm = ls0.clone(), lm0.clone()
|
| 693 |
best_codes = codes0.clone()
|
| 694 |
-
|
| 695 |
d, m, ls, lm, codes = best_d.clone(), best_m.clone(), best_ls.clone(), best_lm.clone(), best_codes.clone()
|
| 696 |
|
| 697 |
ls_deltas = torch.tensor([-3, -2, -1, 0, 1, 2, 3], dtype=torch.int64, device=device)
|
|
@@ -701,10 +699,10 @@ def _refine_trajectory_cuda(
|
|
| 701 |
|
| 702 |
for _ in range(cfg.refine_passes):
|
| 703 |
d_new, m_new = _extended_dm_solve_and_ulp_cuda(X, W, ls, lm, codes, d, m, carry, cfg)
|
| 704 |
-
|
| 705 |
-
imp_dm =
|
| 706 |
if torch.any(imp_dm):
|
| 707 |
-
|
| 708 |
best_d = torch.where(imp_dm, d_new, best_d)
|
| 709 |
best_m = torch.where(imp_dm, m_new, best_m)
|
| 710 |
best_ls = torch.where(imp_dm[:, None], ls, best_ls)
|
|
@@ -713,10 +711,10 @@ def _refine_trajectory_cuda(
|
|
| 713 |
d, m = best_d.clone(), best_m.clone()
|
| 714 |
|
| 715 |
codes_re = _codes_from_params_t(X, d, m, ls, lm)
|
| 716 |
-
|
| 717 |
-
imp_re =
|
| 718 |
if torch.any(imp_re):
|
| 719 |
-
|
| 720 |
best_codes = torch.where(imp_re[:, None], codes_re, best_codes)
|
| 721 |
codes = best_codes.clone()
|
| 722 |
|
|
@@ -766,10 +764,10 @@ def _refine_trajectory_cuda(
|
|
| 766 |
lm_try = cand_lm[b_idx, s_idx, pick].to(torch.uint8)
|
| 767 |
codes_try = _codes_from_params_t(X, d, m, ls_try, lm_try)
|
| 768 |
d_try, m_try = _extended_dm_solve_and_ulp_cuda(X, W, ls_try, lm_try, codes_try, d, m, carry, cfg)
|
| 769 |
-
|
| 770 |
-
imp_sub =
|
| 771 |
if torch.any(imp_sub):
|
| 772 |
-
|
| 773 |
best_d = torch.where(imp_sub, d_try, best_d)
|
| 774 |
best_m = torch.where(imp_sub, m_try, best_m)
|
| 775 |
best_ls = torch.where(imp_sub[:, None], ls_try, best_ls)
|
|
@@ -777,7 +775,7 @@ def _refine_trajectory_cuda(
|
|
| 777 |
best_codes = torch.where(imp_sub[:, None], codes_try, best_codes)
|
| 778 |
d, m, ls, lm, codes = best_d.clone(), best_m.clone(), best_ls.clone(), best_lm.clone(), best_codes.clone()
|
| 779 |
|
| 780 |
-
return best_d, best_m, best_ls, best_lm, best_codes,
|
| 781 |
|
| 782 |
|
| 783 |
def _compute_dc_carry_fast(
|
|
@@ -1003,13 +1001,19 @@ def quantize_cuda(
|
|
| 1003 |
_check_stop()
|
| 1004 |
stop = min(start + batch_blocks, n_blocks)
|
| 1005 |
X_t = torch.from_numpy(X_np[start:stop]).to(dev)
|
| 1006 |
-
|
| 1007 |
-
torch.ones_like(X_t)
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
|
| 1011 |
-
|
| 1012 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1013 |
|
| 1014 |
scales_seed[start:stop] = seeds_t["scales"].cpu().numpy()
|
| 1015 |
mins_seed[start:stop] = seeds_t["mins"].cpu().numpy()
|
|
@@ -1020,12 +1024,13 @@ def quantize_cuda(
|
|
| 1020 |
X_t, W_t, seeds_t["scales"], seeds_t["mins"], bd_t, bm_t, cfg
|
| 1021 |
)
|
| 1022 |
sd_t, sm_t, sls_t, slm_t, sc_t, sobj_t = _standalone_coupled_solve_cuda(X_t, W_t, cfg)
|
|
|
|
| 1023 |
solo_d[start:stop] = sd_t.cpu().numpy()
|
| 1024 |
solo_m[start:stop] = sm_t.cpu().numpy()
|
| 1025 |
solo_ls[start:stop] = sls_t.cpu().numpy()
|
| 1026 |
solo_lm[start:stop] = slm_t.cpu().numpy()
|
| 1027 |
solo_codes[start:stop] = sc_t.cpu().numpy()
|
| 1028 |
-
solo_obj[start:stop] =
|
| 1029 |
|
| 1030 |
elapsed = max(time.time() - t0, 1.0e-6)
|
| 1031 |
rate = stop / elapsed
|
|
@@ -1067,11 +1072,17 @@ def quantize_cuda(
|
|
| 1067 |
stop = min(start + batch_blocks, n_blocks)
|
| 1068 |
B_c = stop - start
|
| 1069 |
X_t = torch.from_numpy(X_np[start:stop]).to(dev)
|
| 1070 |
-
|
| 1071 |
-
torch.ones_like(X_t)
|
| 1072 |
-
|
| 1073 |
-
|
| 1074 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1075 |
Xb = X_t.reshape(B_c, NS, 16)
|
| 1076 |
Wb = W_t.reshape(B_c, NS, 16)
|
| 1077 |
Sw = torch.sum(Wb, dim=2)
|
|
|
|
| 223 |
return d, codes.to(torch.uint8)
|
| 224 |
|
| 225 |
|
| 226 |
+
def _block_clamp_cuda(X: "torch.Tensor", cfg: HPCConfig) -> "torch.Tensor":
|
| 227 |
+
"""Per-block kurtosis-gated outlier clamp thresholds on GPU (shape (B, 1, 1))."""
|
| 228 |
+
b2 = X * X
|
| 229 |
+
mean_sq = torch.mean(b2, dim=1)
|
| 230 |
+
mean_4 = torch.mean(b2 * b2, dim=1)
|
| 231 |
+
kurt = torch.where(mean_sq > 1.0e-30, mean_4 / torch.clamp(mean_sq * mean_sq, min=1.0e-30), torch.full_like(mean_sq, 3.0))
|
| 232 |
+
sigma = torch.sqrt(torch.clamp(mean_sq, min=0.0))
|
| 233 |
+
mult = torch.where(
|
| 234 |
+
kurt <= cfg.clamp_kurtosis_off,
|
| 235 |
+
torch.full_like(kurt, 1.0e9),
|
| 236 |
+
torch.where(
|
| 237 |
+
kurt <= cfg.clamp_kurtosis_soft,
|
| 238 |
+
torch.full_like(kurt, float(cfg.clamp_sigma_soft)),
|
| 239 |
+
torch.full_like(kurt, float(cfg.clamp_sigma_hard)),
|
| 240 |
+
),
|
| 241 |
+
)
|
| 242 |
+
clamp = torch.where(mean_sq > 1.0e-30, sigma * mult, torch.full_like(sigma, float("inf")))
|
| 243 |
+
return clamp[:, None, None]
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
def _build_seeds_cuda(X: "torch.Tensor", W: "torch.Tensor | None", cfg: HPCConfig):
|
| 247 |
B = X.shape[0]
|
| 248 |
blocks = X.reshape(B, 16, 16)
|
| 249 |
+
per_blk_clamp = _block_clamp_cuda(X, cfg)
|
| 250 |
+
clipped = torch.clamp(blocks, min=-per_blk_clamp, max=per_blk_clamp)
|
| 251 |
if W is None:
|
| 252 |
sigma_sq = torch.mean(blocks * blocks, dim=(1, 2), keepdim=True)
|
| 253 |
weights = torch.sqrt(sigma_sq + clipped * clipped)
|
|
|
|
| 269 |
"dmin": dmin,
|
| 270 |
"ls": ls,
|
| 271 |
"lm": lm,
|
| 272 |
+
"clamp": per_blk_clamp.reshape(B, 1),
|
| 273 |
}
|
| 274 |
|
| 275 |
|
| 276 |
+
def _phase2_wls_cuda(X: "torch.Tensor", W: "torch.Tensor", seeds: dict):
|
| 277 |
+
per_blk_clamp = seeds["clamp"]
|
| 278 |
+
clipped = torch.clamp(X, min=-per_blk_clamp, max=per_blk_clamp)
|
| 279 |
base_d = seeds["d"].clone()
|
| 280 |
base_m = seeds["dmin"].clone()
|
| 281 |
ls = seeds["ls"].clone()
|
| 282 |
lm = seeds["lm"].clone()
|
| 283 |
scales = seeds["scales"]
|
| 284 |
mins = seeds["mins"]
|
|
|
|
|
|
|
| 285 |
|
| 286 |
for _ in range(5):
|
| 287 |
codes = _codes_from_params_t(clipped, base_d, base_m, ls, lm).to(torch.float32)
|
|
|
|
| 297 |
s_det = torch.where(valid, det, torch.ones_like(det))
|
| 298 |
d_new = (Sbb * Sxa - Sab * Sxb) / s_det
|
| 299 |
m_new = (Sab * Sxa - Saa * Sxb) / s_det
|
| 300 |
+
upd_d = valid & (d_new > 0.0) & torch.isfinite(d_new)
|
| 301 |
+
upd_m = valid & (m_new > 0.0) & torch.isfinite(m_new)
|
| 302 |
base_d = torch.where(upd_d, _round_fp16_t(d_new), base_d)
|
| 303 |
base_m = torch.where(upd_m, _round_fp16_t(m_new), base_m)
|
| 304 |
sd = torch.where(base_d > 1.0e-15, base_d, torch.ones_like(base_d))
|
|
|
|
| 605 |
d = _round_fp16_t(d)
|
| 606 |
m = _round_fp16_t(m)
|
| 607 |
codes = _codes_from_params_t(X, d, m, ls, lm)
|
| 608 |
+
_, sse_cur = _objective_t(X, W, d, m, ls, lm, codes, None, cfg)
|
| 609 |
+
take = sse_cur < best_obj - 1.0e-12
|
| 610 |
if torch.any(take):
|
| 611 |
+
best_obj = torch.where(take, sse_cur, best_obj)
|
| 612 |
best_d = torch.where(take, d, best_d)
|
| 613 |
best_m = torch.where(take, m, best_m)
|
| 614 |
best_ls = torch.where(take[:, None], ls, best_ls)
|
|
|
|
| 638 |
Sxa = torch.sum(W * X * A, dim=1)
|
| 639 |
Sxb = torch.sum(W * X * Bm, dim=1)
|
| 640 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 641 |
det = Saa * Sbb - Sab * Sab
|
| 642 |
valid = det > 1.0e-30
|
| 643 |
s_det = torch.where(valid, det, torch.ones_like(det))
|
|
|
|
| 689 |
best_d, best_m = d0.clone(), m0.clone()
|
| 690 |
best_ls, best_lm = ls0.clone(), lm0.clone()
|
| 691 |
best_codes = codes0.clone()
|
| 692 |
+
_, best_sse = _objective_t(X, W, best_d, best_m, best_ls, best_lm, best_codes, carry, cfg)
|
| 693 |
d, m, ls, lm, codes = best_d.clone(), best_m.clone(), best_ls.clone(), best_lm.clone(), best_codes.clone()
|
| 694 |
|
| 695 |
ls_deltas = torch.tensor([-3, -2, -1, 0, 1, 2, 3], dtype=torch.int64, device=device)
|
|
|
|
| 699 |
|
| 700 |
for _ in range(cfg.refine_passes):
|
| 701 |
d_new, m_new = _extended_dm_solve_and_ulp_cuda(X, W, ls, lm, codes, d, m, carry, cfg)
|
| 702 |
+
_, sse_dm = _objective_t(X, W, d_new, m_new, ls, lm, codes, carry, cfg)
|
| 703 |
+
imp_dm = sse_dm < best_sse - 1.0e-12
|
| 704 |
if torch.any(imp_dm):
|
| 705 |
+
best_sse = torch.where(imp_dm, sse_dm, best_sse)
|
| 706 |
best_d = torch.where(imp_dm, d_new, best_d)
|
| 707 |
best_m = torch.where(imp_dm, m_new, best_m)
|
| 708 |
best_ls = torch.where(imp_dm[:, None], ls, best_ls)
|
|
|
|
| 711 |
d, m = best_d.clone(), best_m.clone()
|
| 712 |
|
| 713 |
codes_re = _codes_from_params_t(X, d, m, ls, lm)
|
| 714 |
+
_, sse_re = _objective_t(X, W, d, m, ls, lm, codes_re, carry, cfg)
|
| 715 |
+
imp_re = sse_re < best_sse - 1.0e-12
|
| 716 |
if torch.any(imp_re):
|
| 717 |
+
best_sse = torch.where(imp_re, sse_re, best_sse)
|
| 718 |
best_codes = torch.where(imp_re[:, None], codes_re, best_codes)
|
| 719 |
codes = best_codes.clone()
|
| 720 |
|
|
|
|
| 764 |
lm_try = cand_lm[b_idx, s_idx, pick].to(torch.uint8)
|
| 765 |
codes_try = _codes_from_params_t(X, d, m, ls_try, lm_try)
|
| 766 |
d_try, m_try = _extended_dm_solve_and_ulp_cuda(X, W, ls_try, lm_try, codes_try, d, m, carry, cfg)
|
| 767 |
+
_, sse_try = _objective_t(X, W, d_try, m_try, ls_try, lm_try, codes_try, carry, cfg)
|
| 768 |
+
imp_sub = sse_try < best_sse - 1.0e-12
|
| 769 |
if torch.any(imp_sub):
|
| 770 |
+
best_sse = torch.where(imp_sub, sse_try, best_sse)
|
| 771 |
best_d = torch.where(imp_sub, d_try, best_d)
|
| 772 |
best_m = torch.where(imp_sub, m_try, best_m)
|
| 773 |
best_ls = torch.where(imp_sub[:, None], ls_try, best_ls)
|
|
|
|
| 775 |
best_codes = torch.where(imp_sub[:, None], codes_try, best_codes)
|
| 776 |
d, m, ls, lm, codes = best_d.clone(), best_m.clone(), best_ls.clone(), best_lm.clone(), best_codes.clone()
|
| 777 |
|
| 778 |
+
return best_d, best_m, best_ls, best_lm, best_codes, best_sse
|
| 779 |
|
| 780 |
|
| 781 |
def _compute_dc_carry_fast(
|
|
|
|
| 1001 |
_check_stop()
|
| 1002 |
stop = min(start + batch_blocks, n_blocks)
|
| 1003 |
X_t = torch.from_numpy(X_np[start:stop]).to(dev)
|
| 1004 |
+
if W_np is None:
|
| 1005 |
+
W_t = torch.ones_like(X_t)
|
| 1006 |
+
else:
|
| 1007 |
+
W_raw_t = torch.from_numpy(W_np[start:stop]).to(dev)
|
| 1008 |
+
if cfg.temper_imatrix:
|
| 1009 |
+
sig2_t = torch.mean(X_t * X_t, dim=1, keepdim=True)
|
| 1010 |
+
W_t = torch.sqrt(torch.clamp(W_raw_t, min=1.0e-6)) * torch.sqrt(sig2_t + X_t * X_t)
|
| 1011 |
+
wm_t = torch.mean(W_t, dim=1, keepdim=True)
|
| 1012 |
+
W_t = torch.where(wm_t > 1.0e-30, W_t / torch.clamp(wm_t, min=1.0e-30), torch.ones_like(W_t))
|
| 1013 |
+
else:
|
| 1014 |
+
W_t = W_raw_t
|
| 1015 |
+
seeds_t = _build_seeds_cuda(X_t, None if W_np is None else W_t, cfg)
|
| 1016 |
+
bd_t, bm_t = _phase2_wls_cuda(X_t, W_t, seeds_t)
|
| 1017 |
|
| 1018 |
scales_seed[start:stop] = seeds_t["scales"].cpu().numpy()
|
| 1019 |
mins_seed[start:stop] = seeds_t["mins"].cpu().numpy()
|
|
|
|
| 1024 |
X_t, W_t, seeds_t["scales"], seeds_t["mins"], bd_t, bm_t, cfg
|
| 1025 |
)
|
| 1026 |
sd_t, sm_t, sls_t, slm_t, sc_t, sobj_t = _standalone_coupled_solve_cuda(X_t, W_t, cfg)
|
| 1027 |
+
_, sse_Solo = _objective_t(X_t, W_t, sd_t, sm_t, sls_t, slm_t, sc_t, None, cfg)
|
| 1028 |
solo_d[start:stop] = sd_t.cpu().numpy()
|
| 1029 |
solo_m[start:stop] = sm_t.cpu().numpy()
|
| 1030 |
solo_ls[start:stop] = sls_t.cpu().numpy()
|
| 1031 |
solo_lm[start:stop] = slm_t.cpu().numpy()
|
| 1032 |
solo_codes[start:stop] = sc_t.cpu().numpy()
|
| 1033 |
+
solo_obj[start:stop] = sse_Solo.cpu().numpy()
|
| 1034 |
|
| 1035 |
elapsed = max(time.time() - t0, 1.0e-6)
|
| 1036 |
rate = stop / elapsed
|
|
|
|
| 1072 |
stop = min(start + batch_blocks, n_blocks)
|
| 1073 |
B_c = stop - start
|
| 1074 |
X_t = torch.from_numpy(X_np[start:stop]).to(dev)
|
| 1075 |
+
if W_np is None:
|
| 1076 |
+
W_t = torch.ones_like(X_t)
|
| 1077 |
+
else:
|
| 1078 |
+
W_raw_t = torch.from_numpy(W_np[start:stop]).to(dev)
|
| 1079 |
+
if cfg.temper_imatrix:
|
| 1080 |
+
sig2_t = torch.mean(X_t * X_t, dim=1, keepdim=True)
|
| 1081 |
+
W_t = torch.sqrt(torch.clamp(W_raw_t, min=1.0e-6)) * torch.sqrt(sig2_t + X_t * X_t)
|
| 1082 |
+
wm_t = torch.mean(W_t, dim=1, keepdim=True)
|
| 1083 |
+
W_t = torch.where(wm_t > 1.0e-30, W_t / torch.clamp(wm_t, min=1.0e-30), torch.ones_like(W_t))
|
| 1084 |
+
else:
|
| 1085 |
+
W_t = W_raw_t
|
| 1086 |
Xb = X_t.reshape(B_c, NS, 16)
|
| 1087 |
Wb = W_t.reshape(B_c, NS, 16)
|
| 1088 |
Sw = torch.sum(Wb, dim=2)
|
gguf.py
CHANGED
|
@@ -254,11 +254,17 @@ def _dequantize(raw: bytes, ti: TensorInfo) -> np.ndarray:
|
|
| 254 |
return (d[:, None] * q).reshape(-1)
|
| 255 |
if t == GGML_TYPE_Q2_K:
|
| 256 |
blocks = np.frombuffer(raw, dtype=np.uint8).reshape(-1, 84)
|
|
|
|
| 257 |
scales = blocks[:, :16]
|
| 258 |
qs = blocks[:, 16:80]
|
| 259 |
d = blocks[:, 80:82].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 260 |
dmin = blocks[:, 82:84].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 261 |
-
codes = np.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
return dequantize_params_batch(d, dmin, scales & 0x0F, scales >> 4, codes).reshape(-1)
|
| 263 |
raise ValueError(f"unsupported source GGUF type {ti.type_name} for {ti.name}")
|
| 264 |
|
|
|
|
| 254 |
return (d[:, None] * q).reshape(-1)
|
| 255 |
if t == GGML_TYPE_Q2_K:
|
| 256 |
blocks = np.frombuffer(raw, dtype=np.uint8).reshape(-1, 84)
|
| 257 |
+
n = blocks.shape[0]
|
| 258 |
scales = blocks[:, :16]
|
| 259 |
qs = blocks[:, 16:80]
|
| 260 |
d = blocks[:, 80:82].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 261 |
dmin = blocks[:, 82:84].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 262 |
+
codes = np.empty((n, QK_K), dtype=np.uint8)
|
| 263 |
+
for base in (0, 128):
|
| 264 |
+
q = qs[:, base // 4 : base // 4 + 32]
|
| 265 |
+
for s_lvl in range(4):
|
| 266 |
+
lo = base + 32 * s_lvl
|
| 267 |
+
codes[:, lo : lo + 32] = (q >> np.uint8(2 * s_lvl)) & np.uint8(3)
|
| 268 |
return dequantize_params_batch(d, dmin, scales & 0x0F, scales >> 4, codes).reshape(-1)
|
| 269 |
raise ValueError(f"unsupported source GGUF type {ti.type_name} for {ti.name}")
|
| 270 |
|
pipeline.py
CHANGED
|
@@ -52,7 +52,7 @@ from .q2k import (
|
|
| 52 |
unpack_codes,
|
| 53 |
weighted_sse,
|
| 54 |
)
|
| 55 |
-
from .seeds import build_seeds, seed_clamp_value
|
| 56 |
from .sieve import block_chain_edges, sieve_measure_chain, subblock_chain_edges
|
| 57 |
from .spectral import dc_nudge_codes, fold_weights, objective, refine_codes_hadamard
|
| 58 |
from .viterbi import robust_temperature, viterbi_select
|
|
@@ -86,9 +86,10 @@ class QuantizedTensor:
|
|
| 86 |
return np.concatenate([b.dequantize() for b in self.blocks])
|
| 87 |
|
| 88 |
|
| 89 |
-
def _phase2_wls(X, W, seeds,
|
| 90 |
n = X.shape[0]
|
| 91 |
-
|
|
|
|
| 92 |
base_d = seeds["d"].astype(np.float64).copy()
|
| 93 |
base_m = seeds["dmin"].astype(np.float64).copy()
|
| 94 |
ls = seeds["ls"].copy()
|
|
@@ -111,8 +112,8 @@ def _phase2_wls(X, W, seeds, clamp_val):
|
|
| 111 |
safe_det = np.where(valid, det, 1.0)
|
| 112 |
d_new = (Sbb * Sxa - Sab * Sxb) / safe_det
|
| 113 |
m_new = (Sab * Sxa - Saa * Sxb) / safe_det
|
| 114 |
-
upd_d = valid & (d_new > 0.0) &
|
| 115 |
-
upd_m = valid & (m_new > 0.0) &
|
| 116 |
base_d = np.where(upd_d, round_fp16(d_new.astype(np.float32)).astype(np.float64), base_d)
|
| 117 |
base_m = np.where(upd_m, round_fp16(m_new.astype(np.float32)).astype(np.float64), base_m)
|
| 118 |
|
|
@@ -412,7 +413,7 @@ def _batch_extended_dm_solve_and_ulp(
|
|
| 412 |
carry: np.ndarray,
|
| 413 |
cfg: HPCConfig,
|
| 414 |
) -> tuple[np.ndarray, np.ndarray]:
|
| 415 |
-
"""Closed-form 2x2 Cramer solve + O(1) quadratic ULP polish on
|
| 416 |
N = X_f64.shape[0]
|
| 417 |
A = np.repeat(ls.astype(np.float64), 16, axis=1) * codes.astype(np.float64)
|
| 418 |
B = np.repeat(lm.astype(np.float64), 16, axis=1)
|
|
@@ -422,29 +423,6 @@ def _batch_extended_dm_solve_and_ulp(
|
|
| 422 |
Sxa = np.sum(W_f64 * X_f64 * A, axis=1)
|
| 423 |
Sxb = np.sum(W_f64 * X_f64 * B, axis=1)
|
| 424 |
|
| 425 |
-
if cfg.use_spectral:
|
| 426 |
-
if cfg.vw_lambda > 0.0:
|
| 427 |
-
vw_w = float(cfg.vw_lambda) / QK_K
|
| 428 |
-
half = QK_K // 2
|
| 429 |
-
Ap = A[:, :half] + A[:, half:]
|
| 430 |
-
Bp = B[:, :half] + B[:, half:]
|
| 431 |
-
Xp = X_f64[:, :half] + X_f64[:, half:]
|
| 432 |
-
Saa += vw_w * np.sum(Ap * Ap, axis=1)
|
| 433 |
-
Sab += vw_w * np.sum(Ap * Bp, axis=1)
|
| 434 |
-
Sbb += vw_w * np.sum(Bp * Bp, axis=1)
|
| 435 |
-
Sxa += vw_w * np.sum(Xp * Ap, axis=1)
|
| 436 |
-
Sxb += vw_w * np.sum(Xp * Bp, axis=1)
|
| 437 |
-
if cfg.dc_lambda > 0.0:
|
| 438 |
-
dc_w = float(cfg.dc_lambda) / QK_K
|
| 439 |
-
rA = np.sum(A, axis=1)
|
| 440 |
-
rB = np.sum(B, axis=1)
|
| 441 |
-
rS = np.sum(X_f64, axis=1) + carry.astype(np.float64)
|
| 442 |
-
Saa += dc_w * rA * rA
|
| 443 |
-
Sab += dc_w * rA * rB
|
| 444 |
-
Sbb += dc_w * rB * rB
|
| 445 |
-
Sxa += dc_w * rS * rA
|
| 446 |
-
Sxb += dc_w * rS * rB
|
| 447 |
-
|
| 448 |
det = Saa * Sbb - Sab * Sab
|
| 449 |
valid = det > 1.0e-30
|
| 450 |
s_det = np.where(valid, det, 1.0)
|
|
@@ -578,7 +556,7 @@ def _refine_trajectory_algebraic(
|
|
| 578 |
for _ in range(cfg.refine_passes):
|
| 579 |
d_new, m_new = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, ls, lm, codes, d, m, carry, cfg)
|
| 580 |
obj_dm, sse_dm = _batch_objective(X, W_f64, d_new, m_new, ls, lm, codes, carry, cfg)
|
| 581 |
-
imp_dm =
|
| 582 |
if np.any(imp_dm):
|
| 583 |
best_obj = np.where(imp_dm, obj_dm, best_obj)
|
| 584 |
best_sse = np.where(imp_dm, sse_dm, best_sse)
|
|
@@ -591,7 +569,7 @@ def _refine_trajectory_algebraic(
|
|
| 591 |
|
| 592 |
codes_re = codes_from_params_batch(X, d, m, ls, lm)
|
| 593 |
obj_re, sse_re = _batch_objective(X, W_f64, d, m, ls, lm, codes_re, carry, cfg)
|
| 594 |
-
imp_re =
|
| 595 |
if np.any(imp_re):
|
| 596 |
best_obj = np.where(imp_re, obj_re, best_obj)
|
| 597 |
best_sse = np.where(imp_re, sse_re, best_sse)
|
|
@@ -645,7 +623,7 @@ def _refine_trajectory_algebraic(
|
|
| 645 |
codes_try = codes_from_params_batch(X, d, m, ls_try, lm_try)
|
| 646 |
d_try, m_try = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, ls_try, lm_try, codes_try, d, m, carry, cfg)
|
| 647 |
obj_try, sse_try = _batch_objective(X, W_f64, d_try, m_try, ls_try, lm_try, codes_try, carry, cfg)
|
| 648 |
-
imp_sub =
|
| 649 |
if np.any(imp_sub):
|
| 650 |
best_obj = np.where(imp_sub, obj_try, best_obj)
|
| 651 |
best_sse = np.where(imp_sub, sse_try, best_sse)
|
|
@@ -659,7 +637,7 @@ def _refine_trajectory_algebraic(
|
|
| 659 |
refined = _batch_algebraic_refine_codes(X_f64, W_f64, best_d, best_m, best_ls, best_lm, best_codes, carry, cfg)
|
| 660 |
d_r, m_r = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, best_ls, best_lm, refined, best_d, best_m, carry, cfg)
|
| 661 |
obj_r, sse_r = _batch_objective(X, W_f64, d_r, m_r, best_ls, best_lm, refined, carry, cfg)
|
| 662 |
-
imp_r = obj_r < best_obj - 1.0e-15
|
| 663 |
if np.any(imp_r):
|
| 664 |
best_obj = np.where(imp_r, obj_r, best_obj)
|
| 665 |
best_sse = np.where(imp_r, sse_r, best_sse)
|
|
@@ -702,7 +680,7 @@ def _phase4_algebraic_batch(
|
|
| 702 |
lm_v = np.where(m_v[:, None] > 1.0e-15, np.clip(nearest_int(mins_seed / sm_v), 0, 15), 0).astype(np.uint8)
|
| 703 |
codes_v = codes_from_params_batch(X, d_v, m_v, ls_v, lm_v)
|
| 704 |
|
| 705 |
-
d1, m1, ls1, lm1, c1,
|
| 706 |
X, X_f64, W_f64, Xb, Wb, Sw, Sx, safe_Sw, d_v, m_v, ls_v, lm_v, codes_v, carry, cfg
|
| 707 |
)
|
| 708 |
cand_hits = 0
|
|
@@ -714,10 +692,10 @@ def _phase4_algebraic_batch(
|
|
| 714 |
ls_f = np.stack([f.ls for f in standalone], axis=0)
|
| 715 |
lm_f = np.stack([f.lm for f in standalone], axis=0)
|
| 716 |
codes_f = np.stack([f.codes for f in standalone], axis=0)
|
| 717 |
-
d2, m2, ls2, lm2, c2,
|
| 718 |
X, X_f64, W_f64, Xb, Wb, Sw, Sx, safe_Sw, d_f, m_f, ls_f, lm_f, codes_f, carry, cfg
|
| 719 |
)
|
| 720 |
-
take2 =
|
| 721 |
fac_hits = int(np.sum(take2))
|
| 722 |
d1 = np.where(take2, d2, d1)
|
| 723 |
m1 = np.where(take2, m2, m1)
|
|
@@ -911,7 +889,17 @@ class Q2KQuantizer:
|
|
| 911 |
raise ValueError("importance must match the weight count")
|
| 912 |
if np.any(imp < 0.0) or not np.all(np.isfinite(imp)):
|
| 913 |
raise ValueError("importance must be finite and non-negative")
|
| 914 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 915 |
else:
|
| 916 |
W = None
|
| 917 |
|
|
@@ -934,7 +922,7 @@ class Q2KQuantizer:
|
|
| 934 |
f"Solving 5-iteration WLS across {n_blocks} superblocks",
|
| 935 |
sigma=sigma,
|
| 936 |
)
|
| 937 |
-
base_d, base_m = _phase2_wls(X, W, seeds,
|
| 938 |
|
| 939 |
candidate_errors = np.full((n_blocks, TOTAL_CANDIDATES), np.inf, dtype=np.float32)
|
| 940 |
standalone: list[FactorResult] = []
|
|
|
|
| 52 |
unpack_codes,
|
| 53 |
weighted_sse,
|
| 54 |
)
|
| 55 |
+
from .seeds import block_clamp_values, build_seeds, seed_clamp_value
|
| 56 |
from .sieve import block_chain_edges, sieve_measure_chain, subblock_chain_edges
|
| 57 |
from .spectral import dc_nudge_codes, fold_weights, objective, refine_codes_hadamard
|
| 58 |
from .viterbi import robust_temperature, viterbi_select
|
|
|
|
| 86 |
return np.concatenate([b.dequantize() for b in self.blocks])
|
| 87 |
|
| 88 |
|
| 89 |
+
def _phase2_wls(X, W, seeds, cfg: HPCConfig):
|
| 90 |
n = X.shape[0]
|
| 91 |
+
per_blk_clamp = block_clamp_values(X, cfg).reshape(n, 1)
|
| 92 |
+
clipped = np.clip(X, -per_blk_clamp, per_blk_clamp).astype(np.float32)
|
| 93 |
base_d = seeds["d"].astype(np.float64).copy()
|
| 94 |
base_m = seeds["dmin"].astype(np.float64).copy()
|
| 95 |
ls = seeds["ls"].copy()
|
|
|
|
| 112 |
safe_det = np.where(valid, det, 1.0)
|
| 113 |
d_new = (Sbb * Sxa - Sab * Sxb) / safe_det
|
| 114 |
m_new = (Sab * Sxa - Saa * Sxb) / safe_det
|
| 115 |
+
upd_d = valid & (d_new > 0.0) & np.isfinite(d_new)
|
| 116 |
+
upd_m = valid & (m_new > 0.0) & np.isfinite(m_new)
|
| 117 |
base_d = np.where(upd_d, round_fp16(d_new.astype(np.float32)).astype(np.float64), base_d)
|
| 118 |
base_m = np.where(upd_m, round_fp16(m_new.astype(np.float32)).astype(np.float64), base_m)
|
| 119 |
|
|
|
|
| 413 |
carry: np.ndarray,
|
| 414 |
cfg: HPCConfig,
|
| 415 |
) -> tuple[np.ndarray, np.ndarray]:
|
| 416 |
+
"""Closed-form 2x2 Cramer solve + O(1) quadratic ULP polish on true weighted SSE."""
|
| 417 |
N = X_f64.shape[0]
|
| 418 |
A = np.repeat(ls.astype(np.float64), 16, axis=1) * codes.astype(np.float64)
|
| 419 |
B = np.repeat(lm.astype(np.float64), 16, axis=1)
|
|
|
|
| 423 |
Sxa = np.sum(W_f64 * X_f64 * A, axis=1)
|
| 424 |
Sxb = np.sum(W_f64 * X_f64 * B, axis=1)
|
| 425 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
det = Saa * Sbb - Sab * Sab
|
| 427 |
valid = det > 1.0e-30
|
| 428 |
s_det = np.where(valid, det, 1.0)
|
|
|
|
| 556 |
for _ in range(cfg.refine_passes):
|
| 557 |
d_new, m_new = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, ls, lm, codes, d, m, carry, cfg)
|
| 558 |
obj_dm, sse_dm = _batch_objective(X, W_f64, d_new, m_new, ls, lm, codes, carry, cfg)
|
| 559 |
+
imp_dm = sse_dm < best_sse - 1.0e-15
|
| 560 |
if np.any(imp_dm):
|
| 561 |
best_obj = np.where(imp_dm, obj_dm, best_obj)
|
| 562 |
best_sse = np.where(imp_dm, sse_dm, best_sse)
|
|
|
|
| 569 |
|
| 570 |
codes_re = codes_from_params_batch(X, d, m, ls, lm)
|
| 571 |
obj_re, sse_re = _batch_objective(X, W_f64, d, m, ls, lm, codes_re, carry, cfg)
|
| 572 |
+
imp_re = sse_re < best_sse - 1.0e-15
|
| 573 |
if np.any(imp_re):
|
| 574 |
best_obj = np.where(imp_re, obj_re, best_obj)
|
| 575 |
best_sse = np.where(imp_re, sse_re, best_sse)
|
|
|
|
| 623 |
codes_try = codes_from_params_batch(X, d, m, ls_try, lm_try)
|
| 624 |
d_try, m_try = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, ls_try, lm_try, codes_try, d, m, carry, cfg)
|
| 625 |
obj_try, sse_try = _batch_objective(X, W_f64, d_try, m_try, ls_try, lm_try, codes_try, carry, cfg)
|
| 626 |
+
imp_sub = sse_try < best_sse - 1.0e-15
|
| 627 |
if np.any(imp_sub):
|
| 628 |
best_obj = np.where(imp_sub, obj_try, best_obj)
|
| 629 |
best_sse = np.where(imp_sub, sse_try, best_sse)
|
|
|
|
| 637 |
refined = _batch_algebraic_refine_codes(X_f64, W_f64, best_d, best_m, best_ls, best_lm, best_codes, carry, cfg)
|
| 638 |
d_r, m_r = _batch_extended_dm_solve_and_ulp(X_f64, W_f64, best_ls, best_lm, refined, best_d, best_m, carry, cfg)
|
| 639 |
obj_r, sse_r = _batch_objective(X, W_f64, d_r, m_r, best_ls, best_lm, refined, carry, cfg)
|
| 640 |
+
imp_r = (sse_r <= best_sse * (1.0 + cfg.sse_budget)) & (obj_r < best_obj - 1.0e-15)
|
| 641 |
if np.any(imp_r):
|
| 642 |
best_obj = np.where(imp_r, obj_r, best_obj)
|
| 643 |
best_sse = np.where(imp_r, sse_r, best_sse)
|
|
|
|
| 680 |
lm_v = np.where(m_v[:, None] > 1.0e-15, np.clip(nearest_int(mins_seed / sm_v), 0, 15), 0).astype(np.uint8)
|
| 681 |
codes_v = codes_from_params_batch(X, d_v, m_v, ls_v, lm_v)
|
| 682 |
|
| 683 |
+
d1, m1, ls1, lm1, c1, _, sse1 = _refine_trajectory_algebraic(
|
| 684 |
X, X_f64, W_f64, Xb, Wb, Sw, Sx, safe_Sw, d_v, m_v, ls_v, lm_v, codes_v, carry, cfg
|
| 685 |
)
|
| 686 |
cand_hits = 0
|
|
|
|
| 692 |
ls_f = np.stack([f.ls for f in standalone], axis=0)
|
| 693 |
lm_f = np.stack([f.lm for f in standalone], axis=0)
|
| 694 |
codes_f = np.stack([f.codes for f in standalone], axis=0)
|
| 695 |
+
d2, m2, ls2, lm2, c2, _, sse2 = _refine_trajectory_algebraic(
|
| 696 |
X, X_f64, W_f64, Xb, Wb, Sw, Sx, safe_Sw, d_f, m_f, ls_f, lm_f, codes_f, carry, cfg
|
| 697 |
)
|
| 698 |
+
take2 = sse2 < sse1 - 1.0e-15
|
| 699 |
fac_hits = int(np.sum(take2))
|
| 700 |
d1 = np.where(take2, d2, d1)
|
| 701 |
m1 = np.where(take2, m2, m1)
|
|
|
|
| 889 |
raise ValueError("importance must match the weight count")
|
| 890 |
if np.any(imp < 0.0) or not np.all(np.isfinite(imp)):
|
| 891 |
raise ValueError("importance must be finite and non-negative")
|
| 892 |
+
W_raw = imp.reshape(n_blocks, QK_K)
|
| 893 |
+
if cfg.temper_imatrix:
|
| 894 |
+
sig2 = np.mean(X.astype(np.float64) ** 2, axis=1, keepdims=True)
|
| 895 |
+
W = (
|
| 896 |
+
np.sqrt(np.maximum(W_raw.astype(np.float64), 1.0e-6))
|
| 897 |
+
* np.sqrt(sig2 + X.astype(np.float64) ** 2)
|
| 898 |
+
)
|
| 899 |
+
w_mean = np.mean(W, axis=1, keepdims=True)
|
| 900 |
+
W = np.where(w_mean > 1.0e-30, W / np.maximum(w_mean, 1.0e-30), 1.0).astype(np.float32)
|
| 901 |
+
else:
|
| 902 |
+
W = W_raw
|
| 903 |
else:
|
| 904 |
W = None
|
| 905 |
|
|
|
|
| 922 |
f"Solving 5-iteration WLS across {n_blocks} superblocks",
|
| 923 |
sigma=sigma,
|
| 924 |
)
|
| 925 |
+
base_d, base_m = _phase2_wls(X, W, seeds, cfg)
|
| 926 |
|
| 927 |
candidate_errors = np.full((n_blocks, TOTAL_CANDIDATES), np.inf, dtype=np.float32)
|
| 928 |
standalone: list[FactorResult] = []
|
seeds.py
CHANGED
|
@@ -156,16 +156,34 @@ def seed_weights(
|
|
| 156 |
return np.sqrt(sigma_sq + np.minimum(block, clamp_val) ** 2)
|
| 157 |
|
| 158 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
def build_seeds(
|
| 160 |
x: np.ndarray,
|
| 161 |
importance: np.ndarray | None,
|
| 162 |
cfg: HPCConfig,
|
| 163 |
-
clamp_val: float = float("inf"),
|
| 164 |
) -> dict[str, np.ndarray]:
|
| 165 |
"""Phase-1 seeds for all blocks: per-sub (scale,min) and shared (d,dmin)."""
|
| 166 |
n_blocks = x.shape[0]
|
| 167 |
blocks = np.asarray(x, dtype=np.float64).reshape(n_blocks, 16, 16)
|
| 168 |
-
|
|
|
|
| 169 |
if importance is None:
|
| 170 |
sigma_sq = np.mean(blocks * blocks, axis=(1, 2), keepdims=True)
|
| 171 |
weights = np.sqrt(sigma_sq + clipped * clipped)
|
|
|
|
| 156 |
return np.sqrt(sigma_sq + np.minimum(block, clamp_val) ** 2)
|
| 157 |
|
| 158 |
|
| 159 |
+
def block_clamp_values(blocks: np.ndarray, cfg: HPCConfig) -> np.ndarray:
|
| 160 |
+
"""Per-block kurtosis-gated outlier clamp thresholds (shape (n_blocks, 1, 1))."""
|
| 161 |
+
b = np.asarray(blocks, dtype=np.float64).reshape(-1, QK_K_SEED := 256)
|
| 162 |
+
b2 = b * b
|
| 163 |
+
mean_sq = np.mean(b2, axis=1)
|
| 164 |
+
mean_fourth = np.mean(b2 * b2, axis=1)
|
| 165 |
+
kurt = np.where(mean_sq > 1.0e-30, mean_fourth / np.maximum(mean_sq * mean_sq, 1.0e-30), 3.0)
|
| 166 |
+
sigma = np.sqrt(np.maximum(mean_sq, 0.0))
|
| 167 |
+
mult = np.where(
|
| 168 |
+
kurt <= cfg.clamp_kurtosis_off,
|
| 169 |
+
1.0e9,
|
| 170 |
+
np.where(kurt <= cfg.clamp_kurtosis_soft, cfg.clamp_sigma_soft, cfg.clamp_sigma_hard),
|
| 171 |
+
)
|
| 172 |
+
clamp = np.where(mean_sq > 1.0e-30, sigma * mult, np.inf)
|
| 173 |
+
return clamp[:, None, None]
|
| 174 |
+
|
| 175 |
+
|
| 176 |
def build_seeds(
|
| 177 |
x: np.ndarray,
|
| 178 |
importance: np.ndarray | None,
|
| 179 |
cfg: HPCConfig,
|
| 180 |
+
clamp_val: float | np.ndarray = float("inf"),
|
| 181 |
) -> dict[str, np.ndarray]:
|
| 182 |
"""Phase-1 seeds for all blocks: per-sub (scale,min) and shared (d,dmin)."""
|
| 183 |
n_blocks = x.shape[0]
|
| 184 |
blocks = np.asarray(x, dtype=np.float64).reshape(n_blocks, 16, 16)
|
| 185 |
+
per_blk_clamp = block_clamp_values(blocks, cfg)
|
| 186 |
+
clipped = np.clip(blocks, -per_blk_clamp, per_blk_clamp)
|
| 187 |
if importance is None:
|
| 188 |
sigma_sq = np.mean(blocks * blocks, axis=(1, 2), keepdims=True)
|
| 189 |
weights = np.sqrt(sigma_sq + clipped * clipped)
|