CompressedGemma commited on
Commit
24227ac
·
verified ·
1 Parent(s): de7e562

Upload 16 files

Browse files
Files changed (5) hide show
  1. config.py +1 -0
  2. cuda_backend.py +69 -58
  3. gguf.py +7 -1
  4. pipeline.py +26 -38
  5. 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 _build_seeds_cuda(X: "torch.Tensor", W: "torch.Tensor | None", clamp_val: float):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  B = X.shape[0]
228
  blocks = X.reshape(B, 16, 16)
229
- clipped = torch.clamp(blocks, min=-clamp_val, max=clamp_val)
 
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, clamp_val: float):
255
- clipped = torch.clamp(X, min=-clamp_val, max=clamp_val)
 
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) & (d_new < 4.0 * (seed_d + 1.0e-10))
280
- upd_m = valid & (m_new > 0.0) & (m_new < 4.0 * (seed_m + 1.0e-10))
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
- obj, _ = _objective_t(X, W, d, m, ls, lm, codes, None, cfg)
588
- take = obj < best_obj - 1.0e-12
589
  if torch.any(take):
590
- best_obj = torch.where(take, obj, best_obj)
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
- best_obj, _ = _objective_t(X, W, best_d, best_m, best_ls, best_lm, best_codes, carry, cfg)
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
- obj_dm, _ = _objective_t(X, W, d_new, m_new, ls, lm, codes, carry, cfg)
705
- imp_dm = obj_dm < best_obj - 1.0e-12
706
  if torch.any(imp_dm):
707
- best_obj = torch.where(imp_dm, obj_dm, best_obj)
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
- obj_re, _ = _objective_t(X, W, d, m, ls, lm, codes_re, carry, cfg)
717
- imp_re = obj_re < best_obj - 1.0e-12
718
  if torch.any(imp_re):
719
- best_obj = torch.where(imp_re, obj_re, best_obj)
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
- obj_try, _ = _objective_t(X, W, d_try, m_try, ls_try, lm_try, codes_try, carry, cfg)
770
- imp_sub = obj_try < best_obj - 1.0e-12
771
  if torch.any(imp_sub):
772
- best_obj = torch.where(imp_sub, obj_try, best_obj)
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, best_obj
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
- W_t = (
1007
- torch.ones_like(X_t)
1008
- if W_np is None
1009
- else torch.from_numpy(W_np[start:stop]).to(dev)
1010
- )
1011
- seeds_t = _build_seeds_cuda(X_t, None if W_np is None else W_t, clamp_val)
1012
- bd_t, bm_t = _phase2_wls_cuda(X_t, W_t, seeds_t, clamp_val)
 
 
 
 
 
 
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] = sobj_t.cpu().numpy()
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
- W_t = (
1071
- torch.ones_like(X_t)
1072
- if W_np is None
1073
- else torch.from_numpy(W_np[start:stop]).to(dev)
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.stack([unpack_codes(q) for q in qs])
 
 
 
 
 
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, clamp_val):
90
  n = X.shape[0]
91
- clipped = np.clip(X, -clamp_val, clamp_val).astype(np.float32)
 
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) & (d_new < 4.0 * (seeds["d"] + 1.0e-10))
115
- upd_m = valid & (m_new > 0.0) & (m_new < 4.0 * (seeds["dmin"] + 1.0e-10))
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 the full extended objective."""
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 = obj_dm < best_obj - 1.0e-15
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 = obj_re < best_obj - 1.0e-15
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 = obj_try < best_obj - 1.0e-15
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, obj1, _ = _refine_trajectory_algebraic(
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, obj2, _ = _refine_trajectory_algebraic(
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 = obj2 < obj1 - 1.0e-15
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
- W = imp.reshape(n_blocks, QK_K)
 
 
 
 
 
 
 
 
 
 
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, clamp_val)
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
- clipped = np.clip(blocks, -clamp_val, clamp_val)
 
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)