CompressedGemma commited on
Commit
dfb9420
·
verified ·
1 Parent(s): b194f36

Revert to keep stock llama compatibility

Browse files
Files changed (7) hide show
  1. __main__.py +0 -34
  2. config.py +0 -19
  3. gguf.py +8 -133
  4. gui.py +15 -96
  5. pipeline.py +1 -77
  6. q3_k.py +2 -41
  7. q4_0.py +0 -14
__main__.py CHANGED
@@ -53,14 +53,6 @@ def _config_from_args(args) -> HPCConfig:
53
  cfg.therm_lambda_tilt = float(args.thermal_tilt)
54
  if args.pin_dc:
55
  cfg.pin_dc = True
56
- if getattr(args, "segment", False):
57
- cfg.segment = True
58
- if getattr(args, "segment_k", None) is not None:
59
- cfg.segment_k = int(args.segment_k)
60
- if getattr(args, "segment_iters", None) is not None:
61
- cfg.segment_iters = int(args.segment_iters)
62
- if getattr(args, "segment_table", None) is not None:
63
- cfg.segment_table_size = int(args.segment_table)
64
  if args.no_q4_fallback:
65
  cfg.enable_q4_fallback = False
66
  if args.keep_embd:
@@ -312,32 +304,6 @@ def main() -> None:
312
  help="zero-DC pin (Q2_K free lunch): re-solve (d, m) on the exact dc=0 line "
313
  "after assembly/thermal; strictly lowers SSE while driving row-DC residual to ~0",
314
  )
315
- parser.add_argument(
316
- "--segment",
317
- action="store_true",
318
- help="band-major superblock segmentation for Q2_K / Q3_K (emits HPCQ.SEG.V1 label channels)",
319
- )
320
- parser.add_argument(
321
- "--segment-k",
322
- type=int,
323
- default=None,
324
- metavar="K",
325
- help="band count k for superblock segmentation (default 16)",
326
- )
327
- parser.add_argument(
328
- "--segment-iters",
329
- type=int,
330
- default=None,
331
- metavar="N",
332
- help="proxy fixed-point rounds for superblock segmentation (default 4)",
333
- )
334
- parser.add_argument(
335
- "--segment-table",
336
- type=int,
337
- default=None,
338
- metavar="M",
339
- help="generalized permutation lookup table size per tensor (default 256 = +0.031 bpw; 0 = full per-block)",
340
- )
341
  parser.add_argument(
342
  "--format",
343
  choices=("mixed", "mixed_q1", "custom", "q1_0", "q3_k", "q4_0", "q2_k"),
 
53
  cfg.therm_lambda_tilt = float(args.thermal_tilt)
54
  if args.pin_dc:
55
  cfg.pin_dc = True
 
 
 
 
 
 
 
 
56
  if args.no_q4_fallback:
57
  cfg.enable_q4_fallback = False
58
  if args.keep_embd:
 
304
  help="zero-DC pin (Q2_K free lunch): re-solve (d, m) on the exact dc=0 line "
305
  "after assembly/thermal; strictly lowers SSE while driving row-DC residual to ~0",
306
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  parser.add_argument(
308
  "--format",
309
  choices=("mixed", "mixed_q1", "custom", "q1_0", "q3_k", "q4_0", "q2_k"),
config.py CHANGED
@@ -103,18 +103,6 @@ class HPCConfig:
103
  # (the Q2_K closed-form pin never spends any). 0 disables the expense.
104
  pin_budget: float = 0.05
105
 
106
- # ---- self-describing segmentation (V2-only, opt-in) -----------------
107
- # Per-superblock deterministic band clustering. Labels are a pure
108
- # function of the block's own dequantized values, so the decoder
109
- # recovers the slot->position permutation by recomputation -- no
110
- # sidecar, GGUF layout untouched. Q2_K / Q3_K use segment_k bands
111
- # over the 256-weight superblock; Q4_0's 32-wide unit block uses k=1
112
- # (ascending value order).
113
- segment: bool = False
114
- segment_k: int = 16
115
- segment_iters: int = 4
116
- segment_table_size: int = 256
117
-
118
  # ---- seed clamp -----------------------------------------------------
119
  clamp_kurtosis_off: float = 6.0
120
  clamp_kurtosis_soft: float = 20.0
@@ -172,13 +160,6 @@ class HPCConfig:
172
  raise ValueError("therm_t_decay must lie in (0, 1)")
173
  if self.therm_lambda_tilt < 1.0:
174
  raise ValueError("therm_lambda_tilt must be >= 1.0 (1.0 = off)")
175
- if self.segment:
176
- if not (2 <= self.segment_k <= 256):
177
- raise ValueError("segment_k must lie in [2, 256]")
178
- if self.segment_iters < 1:
179
- raise ValueError("segment_iters must be >= 1")
180
- if self.segment_table_size < 0 or (0 < self.segment_table_size < 4) or self.segment_table_size > 65535:
181
- raise ValueError("segment_table_size must be 0 (full per-block) or lie in [4, 65535]")
182
  if self.device not in ("auto", "cuda", "cpu") and not self.device.startswith("cuda:"):
183
  raise ValueError("device must be 'auto', 'cuda', 'cuda:N', or 'cpu'")
184
  if self.quant_format not in ("mixed", "mixed_q1", "custom", "q1_0", "q3_k", "q4_0", "q2_k"):
 
103
  # (the Q2_K closed-form pin never spends any). 0 disables the expense.
104
  pin_budget: float = 0.05
105
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  # ---- seed clamp -----------------------------------------------------
107
  clamp_kurtosis_off: float = 6.0
108
  clamp_kurtosis_soft: float = 20.0
 
160
  raise ValueError("therm_t_decay must lie in (0, 1)")
161
  if self.therm_lambda_tilt < 1.0:
162
  raise ValueError("therm_lambda_tilt must be >= 1.0 (1.0 = off)")
 
 
 
 
 
 
 
163
  if self.device not in ("auto", "cuda", "cpu") and not self.device.startswith("cuda:"):
164
  raise ValueError("device must be 'auto', 'cuda', 'cuda:N', or 'cpu'")
165
  if self.quant_format not in ("mixed", "mixed_q1", "custom", "q1_0", "q3_k", "q4_0", "q2_k"):
gguf.py CHANGED
@@ -26,16 +26,8 @@ from .q2k import QK_K, blocks_to_bytes, dequantize_params_batch, unpack_codes
26
  from .q3_k import Q3_K_BLOCK_BYTES, QK3_K, dequantize_q3_k_bytes, quantize_tensor_q3_k
27
  from .q4_0 import Q4_0_BLOCK_BYTES, QK4_0, quantize_tensor_q4_0
28
  from .q1_0 import QK1_0, Q1_0_BLOCK_BYTES, quantize_tensor_q1_0
29
- from .segmentation import (
30
- label_channel_bytes,
31
- pack_label_channel,
32
- recover_order,
33
- scatter_to_original,
34
- unpack_label_channel,
35
- )
36
 
37
  GGUF_MAGIC = 0x46554747
38
- SEG_KV_PREFIX = "HPCQ.SEG.V1."
39
  DEFAULT_ALIGNMENT = 32
40
 
41
  GGML_TYPE_F32 = 0
@@ -282,15 +274,10 @@ class GGUFReader:
282
 
283
  def read_tensor(self, name: str) -> tuple[np.ndarray, int]:
284
  raw = self.read_tensor_raw(name)
285
- x = _dequantize(raw, self.info(name))
286
- return self._unsegment(x, name), self.info(name).row_width
287
 
288
  def iter_tensor_row_chunks(self, name: str, max_elements: int = 8_388_608):
289
- """Stream a tensor in row-aligned float32 chunks to bound peak RAM.
290
-
291
- Chunks are unsegmented: if the tensor carries an HPCQ label channel,
292
- each yielded chunk is scattered back to original order.
293
- """
294
  ti = self.info(name)
295
  row = ti.row_width
296
  blk = BLOCK_SIZE[ti.type]
@@ -298,10 +285,6 @@ class GGUFReader:
298
  x, r = self.read_tensor(name)
299
  yield x, r, 0, ti.n_elements // max(r, 1)
300
  return
301
- seg_2d = None
302
- seg = self.seg_labels(name)
303
- if seg is not None:
304
- seg_2d = seg[0]
305
  n_rows = ti.n_elements // row
306
  rows_per_chunk = max(1, max_elements // row)
307
  bytes_per_row = (row // blk) * BLOCK_BYTES[ti.type]
@@ -314,69 +297,8 @@ class GGUFReader:
314
  raw = f.read(chunk_bytes)
315
  if len(raw) != chunk_bytes:
316
  raise ValueError(f"{name}: truncated tensor data")
317
- sub = _dequantize(raw, TensorInfo(ti.name, (chunk_elems,), ti.type, 0))
318
- if seg_2d is not None:
319
- b0 = r0 * (row // blk)
320
- b1 = b0 + (r1 - r0) * (row // blk)
321
- sub = _scatter_rows(sub, seg_2d[b0:b1])
322
- yield sub, row, r0, r1
323
-
324
- def _seg_content(self, name: str) -> bytes | None:
325
- """Raw packed label channel bytes for ``name`` (undecoded KV value)."""
326
- for key, vtype, raw in self.kv_pairs:
327
- if key == SEG_KV_PREFIX + name:
328
- if vtype == 8:
329
- # legacy: string value, u64 length prefix then raw bytes
330
- if len(raw) < 8:
331
- raise ValueError(f"{name}: corrupt label channel KV")
332
- return raw[8:]
333
- if vtype == 9:
334
- # uint8 array: u32 element type + u64 count + data
335
- if len(raw) < 12:
336
- raise ValueError(f"{name}: corrupt label channel KV")
337
- if struct.unpack("<I", raw[:4])[0] != 0:
338
- raise ValueError(f"{name}: label channel array is not uint8")
339
- n = struct.unpack("<Q", raw[4:12])[0]
340
- if len(raw) < 12 + n:
341
- raise ValueError(f"{name}: truncated label channel array")
342
- return raw[12 : 12 + n]
343
- raise ValueError(f"{name}: label channel KV has bad type {vtype}")
344
- return None
345
- return None
346
-
347
- def seg_labels(self, name: str) -> tuple[np.ndarray, int] | None:
348
- """Decode a tensor's label channel (labels per ORIGINAL position).
349
-
350
- Returns ``(labels_2d, k)`` where ``labels_2d`` is shaped
351
- ``(n_blocks, block_qk)``, or ``None`` when no channel is present.
352
- """
353
- content = self._seg_content(name)
354
- if content is None:
355
- return None
356
- ti = self.info(name)
357
- if ti.type not in (GGML_TYPE_Q2_K, GGML_TYPE_Q3_K):
358
- raise ValueError(f"{name}: label channel on non-segmentable type {ti.type_name}")
359
- blk = QK_K if ti.type == GGML_TYPE_Q2_K else QK3_K
360
- k, labels = unpack_label_channel(content)
361
- if labels.size != ti.n_elements:
362
- raise ValueError(
363
- f"{name}: label channel size {labels.size} != tensor elements {ti.n_elements}"
364
- )
365
- return labels.reshape(ti.n_elements // blk, blk), k
366
-
367
- def _unsegment(self, x: np.ndarray, name: str) -> np.ndarray:
368
- seg = self.seg_labels(name)
369
- if seg is None:
370
- return x
371
- return _scatter_rows(x, seg[0])
372
-
373
-
374
- def _scatter_rows(x: np.ndarray, labels_2d: np.ndarray) -> np.ndarray:
375
- """Scatter slot-order values back to original positions via the channel."""
376
- out = scatter_to_original(
377
- x.reshape(labels_2d.shape).astype(np.float32), recover_order(labels_2d)
378
- )
379
- return out.reshape(-1)
380
 
381
 
382
  def _dequantize(raw: bytes, ti: TensorInfo) -> np.ndarray:
@@ -796,9 +718,6 @@ def write_quantized_gguf(
796
  attn_q4 = bool(getattr(cfg, "promote_attn_q4", False))
797
  q_format = str(getattr(cfg, "quant_format", "mixed"))
798
  custom_map = getattr(cfg, "custom_quant_map", None) or None
799
- seg_active = bool(getattr(cfg, "segment", False))
800
- seg_k = max(2, int(getattr(cfg, "segment_k", 16)))
801
- seg_table_size = int(getattr(cfg, "segment_table_size", 256))
802
 
803
  plan: list[str | None] = []
804
  quantized_count = 0
@@ -893,27 +812,11 @@ def write_quantized_gguf(
893
  ftype_code = 11 if has_q3k else (10 if has_q2k else (40 if has_q1_0 else 2))
894
  kv_pairs = []
895
  for key, vtype, raw in reader.kv_pairs:
896
- if key.startswith(SEG_KV_PREFIX):
897
- continue
898
  if quantized_count and key == "general.file_type" and vtype == 4:
899
  raw = struct.pack("<I", ftype_code)
900
  elif quantized_count and key == "general.quantization_version" and vtype == 4:
901
  raw = struct.pack("<I", 2)
902
  kv_pairs.append((key, vtype, raw))
903
- # Reserve label channels for every planned segmented tensor so the KV
904
- # section layout is final before data streaming; contents are patched
905
- # in place (same length) after each tensor is quantized.
906
- seg_reserve: dict[str, int] = {}
907
- if seg_active:
908
- for ti, fmt in zip(reader.tensors, plan):
909
- if fmt in ("Q2_K", "Q3_K"):
910
- key = SEG_KV_PREFIX + ti.name
911
- content_len = label_channel_bytes(ti.n_elements, seg_k, seg_table_size)
912
- seg_reserve[key] = content_len
913
- # GGUF uint8 array: u32 element type + u64 count + zeros
914
- kv_pairs.append(
915
- (key, 9, struct.pack("<I", 0) + struct.pack("<Q", content_len) + bytes(content_len))
916
- )
917
 
918
  output_path = Path(output_path)
919
  output_path.parent.mkdir(parents=True, exist_ok=True)
@@ -928,22 +831,10 @@ def write_quantized_gguf(
928
  model_t0 = time.time()
929
  with output_path.open("wb") as fout:
930
  fout.write(struct.pack("<IIQQ", GGUF_MAGIC, reader.version, len(out_infos), len(kv_pairs)))
931
- seg_patch_offsets: dict[str, int] = {}
932
  for key, vtype, raw in kv_pairs:
933
  _write_string(fout, key)
934
  fout.write(struct.pack("<I", vtype))
935
- if key in seg_reserve:
936
- seg_patch_offsets[key] = fout.tell()
937
  fout.write(raw)
938
-
939
- def _patch_seg_kv(fout, key: str, labels: np.ndarray) -> None:
940
- packed = pack_label_channel(labels, seg_k, seg_table_size)
941
- if len(packed) != seg_reserve.get(key, -1):
942
- raise RuntimeError(f"{key}: label channel size {len(packed)} != reserved")
943
- pos = fout.tell()
944
- fout.seek(seg_patch_offsets[key] + 12) # skip u32 array type + u64 count
945
- fout.write(packed)
946
- fout.seek(pos)
947
  for ti, out_type, out_size, offset in out_infos:
948
  _write_string(fout, ti.name)
949
  fout.write(struct.pack("<I", len(ti.dims)))
@@ -1027,8 +918,6 @@ def write_quantized_gguf(
1027
  if len(payload) != out_size:
1028
  raise RuntimeError(f"{ti.name}: Q2_K payload size mismatch")
1029
  fout.write(payload)
1030
- if seg_active and res.segment_labels is not None:
1031
- _patch_seg_kv(fout, SEG_KV_PREFIX + ti.name, res.segment_labels)
1032
  total_rmse += res.stats.rmse * res.stats.rmse * x.size
1033
  total_elements += x.size
1034
  total_quantized += 1
@@ -1056,26 +945,14 @@ def write_quantized_gguf(
1056
  sse_q3 = 0.0
1057
  done_q3_blks = 0
1058
  t_q3_start = time.time()
1059
- q3_labels: list[np.ndarray] = []
1060
 
1061
- q3_max_elems = ti.n_elements if seg_active else 8_388_608
1062
- for x_chunk, row, _r0, _r1 in reader.iter_tensor_row_chunks(ti.name, max_elements=q3_max_elems):
1063
  if stop_event is not None and stop_event.is_set():
1064
  raise InterruptedError("Quantization cancelled by user")
1065
  imp_chunk = expand_importance(raw_imp, x_chunk.size, row) if has_imat else None
1066
- if seg_active:
1067
- q3_bytes, nb_chunk, chunk_rmse, chunk_labels = quantize_tensor_q3_k(
1068
- x_chunk,
1069
- importance=imp_chunk,
1070
- cfg=cfg,
1071
- chunk_blocks=8192,
1072
- return_labels=True,
1073
- )
1074
- q3_labels.append(np.asarray(chunk_labels, dtype=np.int64).ravel())
1075
- else:
1076
- q3_bytes, nb_chunk, chunk_rmse = quantize_tensor_q3_k(
1077
- x_chunk, importance=imp_chunk, cfg=cfg, chunk_blocks=8192
1078
- )
1079
  fout.write(q3_bytes)
1080
  written_bytes += len(q3_bytes)
1081
  sse_q3 += (chunk_rmse * chunk_rmse) * x_chunk.size
@@ -1111,8 +988,6 @@ def write_quantized_gguf(
1111
 
1112
  if written_bytes != out_size:
1113
  raise RuntimeError(f"{ti.name}: Q3_K payload size mismatch")
1114
- if seg_active:
1115
- _patch_seg_kv(fout, SEG_KV_PREFIX + ti.name, np.concatenate(q3_labels))
1116
  completed_planned_blocks += eff_tb
1117
  q3_rmse = float(np.sqrt(sse_q3 / ti.n_elements))
1118
  total_rmse += sse_q3
 
26
  from .q3_k import Q3_K_BLOCK_BYTES, QK3_K, dequantize_q3_k_bytes, quantize_tensor_q3_k
27
  from .q4_0 import Q4_0_BLOCK_BYTES, QK4_0, quantize_tensor_q4_0
28
  from .q1_0 import QK1_0, Q1_0_BLOCK_BYTES, quantize_tensor_q1_0
 
 
 
 
 
 
 
29
 
30
  GGUF_MAGIC = 0x46554747
 
31
  DEFAULT_ALIGNMENT = 32
32
 
33
  GGML_TYPE_F32 = 0
 
274
 
275
  def read_tensor(self, name: str) -> tuple[np.ndarray, int]:
276
  raw = self.read_tensor_raw(name)
277
+ return _dequantize(raw, self.info(name)), self.info(name).row_width
 
278
 
279
  def iter_tensor_row_chunks(self, name: str, max_elements: int = 8_388_608):
280
+ """Stream a tensor in row-aligned float32 chunks to bound peak RAM."""
 
 
 
 
281
  ti = self.info(name)
282
  row = ti.row_width
283
  blk = BLOCK_SIZE[ti.type]
 
285
  x, r = self.read_tensor(name)
286
  yield x, r, 0, ti.n_elements // max(r, 1)
287
  return
 
 
 
 
288
  n_rows = ti.n_elements // row
289
  rows_per_chunk = max(1, max_elements // row)
290
  bytes_per_row = (row // blk) * BLOCK_BYTES[ti.type]
 
297
  raw = f.read(chunk_bytes)
298
  if len(raw) != chunk_bytes:
299
  raise ValueError(f"{name}: truncated tensor data")
300
+ sub_ti = TensorInfo(ti.name, (chunk_elems,), ti.type, 0)
301
+ yield _dequantize(raw, sub_ti), row, r0, r1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
 
303
 
304
  def _dequantize(raw: bytes, ti: TensorInfo) -> np.ndarray:
 
718
  attn_q4 = bool(getattr(cfg, "promote_attn_q4", False))
719
  q_format = str(getattr(cfg, "quant_format", "mixed"))
720
  custom_map = getattr(cfg, "custom_quant_map", None) or None
 
 
 
721
 
722
  plan: list[str | None] = []
723
  quantized_count = 0
 
812
  ftype_code = 11 if has_q3k else (10 if has_q2k else (40 if has_q1_0 else 2))
813
  kv_pairs = []
814
  for key, vtype, raw in reader.kv_pairs:
 
 
815
  if quantized_count and key == "general.file_type" and vtype == 4:
816
  raw = struct.pack("<I", ftype_code)
817
  elif quantized_count and key == "general.quantization_version" and vtype == 4:
818
  raw = struct.pack("<I", 2)
819
  kv_pairs.append((key, vtype, raw))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
820
 
821
  output_path = Path(output_path)
822
  output_path.parent.mkdir(parents=True, exist_ok=True)
 
831
  model_t0 = time.time()
832
  with output_path.open("wb") as fout:
833
  fout.write(struct.pack("<IIQQ", GGUF_MAGIC, reader.version, len(out_infos), len(kv_pairs)))
 
834
  for key, vtype, raw in kv_pairs:
835
  _write_string(fout, key)
836
  fout.write(struct.pack("<I", vtype))
 
 
837
  fout.write(raw)
 
 
 
 
 
 
 
 
 
838
  for ti, out_type, out_size, offset in out_infos:
839
  _write_string(fout, ti.name)
840
  fout.write(struct.pack("<I", len(ti.dims)))
 
918
  if len(payload) != out_size:
919
  raise RuntimeError(f"{ti.name}: Q2_K payload size mismatch")
920
  fout.write(payload)
 
 
921
  total_rmse += res.stats.rmse * res.stats.rmse * x.size
922
  total_elements += x.size
923
  total_quantized += 1
 
945
  sse_q3 = 0.0
946
  done_q3_blks = 0
947
  t_q3_start = time.time()
 
948
 
949
+ for x_chunk, row, _r0, _r1 in reader.iter_tensor_row_chunks(ti.name, max_elements=8_388_608):
 
950
  if stop_event is not None and stop_event.is_set():
951
  raise InterruptedError("Quantization cancelled by user")
952
  imp_chunk = expand_importance(raw_imp, x_chunk.size, row) if has_imat else None
953
+ q3_bytes, nb_chunk, chunk_rmse = quantize_tensor_q3_k(
954
+ x_chunk, importance=imp_chunk, cfg=cfg, chunk_blocks=8192
955
+ )
 
 
 
 
 
 
 
 
 
 
956
  fout.write(q3_bytes)
957
  written_bytes += len(q3_bytes)
958
  sse_q3 += (chunk_rmse * chunk_rmse) * x_chunk.size
 
988
 
989
  if written_bytes != out_size:
990
  raise RuntimeError(f"{ti.name}: Q3_K payload size mismatch")
 
 
991
  completed_planned_blocks += eff_tb
992
  q3_rmse = float(np.sqrt(sse_q3 / ti.n_elements))
993
  total_rmse += sse_q3
gui.py CHANGED
@@ -70,12 +70,10 @@ from hpc_quantize_v2 import (
70
  read_imatrix,
71
  )
72
  from hpc_quantize_v2.gguf import (
73
- SEG_KV_PREFIX,
74
  is_q1_0_eligible,
75
  is_q2k_eligible,
76
  is_q3_k_eligible,
77
  is_q4_0_eligible,
78
- label_channel_bytes,
79
  target_quant_type,
80
  tensor_type_key,
81
  write_quantized_gguf,
@@ -186,10 +184,6 @@ class HPCQuantizeGUI:
186
  self.thermal_var = tk.IntVar(value=0)
187
  self.thermal_tilt_var = tk.DoubleVar(value=1.0)
188
  self.pin_dc_var = tk.BooleanVar(value=False)
189
- self.segment_var = tk.BooleanVar(value=False)
190
- self.segment_k_var = tk.IntVar(value=16)
191
- self.segment_iters_var = tk.IntVar(value=4)
192
- self.segment_table_var = tk.IntVar(value=256)
193
 
194
  self.cli_preview_var = tk.StringVar()
195
  self.status_var = tk.StringVar(value="Ready.")
@@ -223,16 +217,8 @@ class HPCQuantizeGUI:
223
  self.promote_attn_q4_var,
224
  self.quant_format_var,
225
  self.thermal_var,
226
- self.thermal_tilt_var,
227
- self.pin_dc_var,
228
- self.segment_var,
229
- self.segment_k_var,
230
- self.segment_iters_var,
231
- self.segment_table_var,
232
  ):
233
  v.trace_add("write", lambda *_: self._update_cli_preview())
234
- for v in (self.segment_var, self.segment_k_var, self.segment_table_var):
235
- v.trace_add("write", lambda *_: self._refresh_plan_view())
236
 
237
  def _apply_theme(self) -> None:
238
  style = ttk.Style(self.root)
@@ -497,30 +483,10 @@ class HPCQuantizeGUI:
497
  text="Pin DC residual to 0 (Q2_K free lunch)",
498
  variable=self.pin_dc_var,
499
  ).grid(row=3, column=0, columnspan=2, sticky=tk.W, padx=4, pady=1)
500
- ttk.Checkbutton(
501
- spec_f,
502
- text="Band-Major Segmentation (Q2_K / Q3_K)",
503
- variable=self.segment_var,
504
- ).grid(row=3, column=2, columnspan=2, sticky=tk.W, padx=4, pady=1)
505
- ttk.Label(spec_f, text="Seg Bands (k):").grid(row=4, column=0, sticky=tk.W, padx=4, pady=2)
506
- ttk.Spinbox(
507
- spec_f, from_=2, to=16, increment=1, textvariable=self.segment_k_var, width=8
508
- ).grid(row=4, column=1, sticky=tk.EW, padx=4, pady=2)
509
- ttk.Label(spec_f, text="Seg Iters:").grid(row=4, column=2, sticky=tk.W, padx=4, pady=2)
510
- ttk.Spinbox(
511
- spec_f, from_=1, to=12, increment=1, textvariable=self.segment_iters_var, width=8
512
- ).grid(row=4, column=3, sticky=tk.EW, padx=4, pady=2)
513
- ttk.Label(spec_f, text="Seg Lookup Table (0=full):").grid(row=5, column=0, columnspan=2, sticky=tk.W, padx=4, pady=2)
514
- ttk.Combobox(
515
- spec_f,
516
- textvariable=self.segment_table_var,
517
- values=(0, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096),
518
- width=8,
519
- ).grid(row=5, column=2, columnspan=2, sticky=tk.EW, padx=4, pady=2)
520
  ttk.Label(
521
  spec_f, text="(λ multiplier ≥1 during thermal anneal; ~1e2–1e3 ≈ zero-coherent-residual '0-error' anneal)",
522
  foreground="#93c5fd",
523
- ).grid(row=6, column=0, columnspan=4, sticky=tk.W, padx=4, pady=(0, 2))
524
 
525
  # Right: GGUF Tensor Browser
526
  browser_frame = ttk.LabelFrame(right_pane, text="3. GGUF Tensor Inspector & Live Status", padding=8)
@@ -850,10 +816,6 @@ class HPCQuantizeGUI:
850
  therm_passes=max(0, int(self.thermal_var.get())),
851
  therm_lambda_tilt=max(1.0, float(self.thermal_tilt_var.get())),
852
  pin_dc=bool(self.pin_dc_var.get()),
853
- segment=bool(self.segment_var.get()),
854
- segment_k=max(2, int(self.segment_k_var.get())),
855
- segment_iters=max(1, int(self.segment_iters_var.get())),
856
- segment_table_size=max(0, int(self.segment_table_var.get())),
857
  quant_format=self.quant_format_var.get(),
858
  custom_quant_map=self._custom_map_for_plan() or {},
859
  enable_q4_fallback=bool(self.q4_fallback_var.get()) and self.quant_format_var.get() not in ("q2_k", "q3_k"),
@@ -907,14 +869,6 @@ class HPCQuantizeGUI:
907
  cmd += ["--thermal-tilt", str(float(self.thermal_tilt_var.get()))]
908
  if self.pin_dc_var.get():
909
  cmd += ["--pin-dc"]
910
- if self.segment_var.get():
911
- cmd += ["--segment"]
912
- if int(self.segment_k_var.get()) != 16:
913
- cmd += ["--segment-k", str(int(self.segment_k_var.get()))]
914
- if int(self.segment_iters_var.get()) != 4:
915
- cmd += ["--segment-iters", str(int(self.segment_iters_var.get()))]
916
- if int(self.segment_table_var.get()) != 256:
917
- cmd += ["--segment-table", str(int(self.segment_table_var.get()))]
918
  cmd.append("--verbose")
919
  return " ".join(shlex.quote(part) for part in cmd)
920
 
@@ -978,43 +932,6 @@ class HPCQuantizeGUI:
978
  self._refresh_plan_view()
979
  self._update_cli_preview()
980
 
981
- def _estimate_seg_bytes(self, ti, tgt: str | None) -> int:
982
- if not bool(self.segment_var.get()) or tgt not in ("Q2_K", "Q3_K"):
983
- return 0
984
- try:
985
- seg_k = max(2, int(self.segment_k_var.get()))
986
- except Exception:
987
- seg_k = 16
988
- try:
989
- seg_tbl = max(0, int(self.segment_table_var.get()))
990
- except Exception:
991
- seg_tbl = 256
992
- content_len = label_channel_bytes(ti.n_elements, seg_k, seg_tbl)
993
- key_len = len((SEG_KV_PREFIX + ti.name).encode("utf-8"))
994
- return 8 + key_len + 4 + 12 + content_len
995
-
996
- def _format_size_summary(self, planned_bytes: int, total_seg_bytes: int) -> str:
997
- if planned_bytes >= 1024 ** 3:
998
- planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
999
- elif planned_bytes >= 1024 ** 2:
1000
- planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
1001
- else:
1002
- planned_text = f"{planned_bytes / 1024:.1f} KiB"
1003
- if total_seg_bytes > 0:
1004
- try:
1005
- seg_tbl = max(0, int(self.segment_table_var.get()))
1006
- except Exception:
1007
- seg_tbl = 256
1008
- if total_seg_bytes >= 1024 ** 3:
1009
- seg_txt = f"+{total_seg_bytes / (1024 ** 3):.2f} GiB"
1010
- elif total_seg_bytes >= 1024 ** 2:
1011
- seg_txt = f"+{total_seg_bytes / (1024 ** 2):.1f} MiB"
1012
- else:
1013
- seg_txt = f"+{total_seg_bytes / 1024:.1f} KiB"
1014
- lut_lbl = f"LUT={seg_tbl}" if seg_tbl > 0 else "full"
1015
- planned_text = f"{planned_text} [seg {seg_txt}, {lut_lbl}]"
1016
- return planned_text
1017
-
1018
  def _refresh_plan_view(self) -> None:
1019
  if self._reader is None:
1020
  return
@@ -1022,8 +939,7 @@ class HPCQuantizeGUI:
1022
  scope_selected = self.mode_var.get() == "selected"
1023
  n_q2, n_q3, n_q4, n_copy = 0, 0, 0, 0
1024
  n_q1 = 0
1025
- planned_bytes = int(getattr(self._reader, "data_start", 0))
1026
- total_seg_bytes = 0
1027
  for ti in self._reader.tensors:
1028
  tgt = self._plan_target(ti, chosen, scope_selected)
1029
  if tgt == "Q2_K":
@@ -1047,9 +963,6 @@ class HPCQuantizeGUI:
1047
  planned_bytes += (ti.n_elements // QK1_0) * Q1_0_BLOCK_BYTES
1048
  else:
1049
  planned_bytes += ti.n_bytes
1050
- seg_b = self._estimate_seg_bytes(ti, tgt)
1051
- planned_bytes += seg_b
1052
- total_seg_bytes += seg_b
1053
 
1054
  if not self.tree.exists(ti.name):
1055
  continue
@@ -1067,7 +980,12 @@ class HPCQuantizeGUI:
1067
  vals[6] = state_str
1068
  self.tree.item(ti.name, tags=(tgt_label,), values=vals)
1069
 
1070
- planned_text = self._format_size_summary(planned_bytes, total_seg_bytes)
 
 
 
 
 
1071
  scope_text = "selected" if scope_selected else "all"
1072
  self.status_var.set(
1073
  f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
@@ -1084,8 +1002,7 @@ class HPCQuantizeGUI:
1084
  plan_filt = self.plan_filter_var.get()
1085
  n_q2, n_q3, n_q4, n_copy = 0, 0, 0, 0
1086
  n_q1 = 0
1087
- planned_bytes = int(getattr(self._reader, "data_start", 0))
1088
- total_seg_bytes = 0
1089
  for ti in self._reader.tensors:
1090
  tgt = self._plan_target(ti, chosen, scope_selected)
1091
  if tgt == "Q2_K":
@@ -1109,9 +1026,6 @@ class HPCQuantizeGUI:
1109
  planned_bytes += (ti.n_elements // QK1_0) * Q1_0_BLOCK_BYTES
1110
  else:
1111
  planned_bytes += ti.n_bytes
1112
- seg_b = self._estimate_seg_bytes(ti, tgt)
1113
- planned_bytes += seg_b
1114
- total_seg_bytes += seg_b
1115
 
1116
  tgt_label = tgt if tgt else "Copy"
1117
  if plan_filt != "ALL" and tgt_label.upper() != plan_filt:
@@ -1153,7 +1067,12 @@ class HPCQuantizeGUI:
1153
  keep_selected = [n for n in chosen if self.tree.exists(n)]
1154
  if keep_selected:
1155
  self.tree.selection_set(keep_selected)
1156
- planned_text = self._format_size_summary(planned_bytes, total_seg_bytes)
 
 
 
 
 
1157
  scope_text = "selected" if scope_selected else "all"
1158
  self.status_var.set(
1159
  f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
 
70
  read_imatrix,
71
  )
72
  from hpc_quantize_v2.gguf import (
 
73
  is_q1_0_eligible,
74
  is_q2k_eligible,
75
  is_q3_k_eligible,
76
  is_q4_0_eligible,
 
77
  target_quant_type,
78
  tensor_type_key,
79
  write_quantized_gguf,
 
184
  self.thermal_var = tk.IntVar(value=0)
185
  self.thermal_tilt_var = tk.DoubleVar(value=1.0)
186
  self.pin_dc_var = tk.BooleanVar(value=False)
 
 
 
 
187
 
188
  self.cli_preview_var = tk.StringVar()
189
  self.status_var = tk.StringVar(value="Ready.")
 
217
  self.promote_attn_q4_var,
218
  self.quant_format_var,
219
  self.thermal_var,
 
 
 
 
 
 
220
  ):
221
  v.trace_add("write", lambda *_: self._update_cli_preview())
 
 
222
 
223
  def _apply_theme(self) -> None:
224
  style = ttk.Style(self.root)
 
483
  text="Pin DC residual to 0 (Q2_K free lunch)",
484
  variable=self.pin_dc_var,
485
  ).grid(row=3, column=0, columnspan=2, sticky=tk.W, padx=4, pady=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  ttk.Label(
487
  spec_f, text="(λ multiplier ≥1 during thermal anneal; ~1e2–1e3 ≈ zero-coherent-residual '0-error' anneal)",
488
  foreground="#93c5fd",
489
+ ).grid(row=4, column=0, columnspan=4, sticky=tk.W, padx=4, pady=(0, 2))
490
 
491
  # Right: GGUF Tensor Browser
492
  browser_frame = ttk.LabelFrame(right_pane, text="3. GGUF Tensor Inspector & Live Status", padding=8)
 
816
  therm_passes=max(0, int(self.thermal_var.get())),
817
  therm_lambda_tilt=max(1.0, float(self.thermal_tilt_var.get())),
818
  pin_dc=bool(self.pin_dc_var.get()),
 
 
 
 
819
  quant_format=self.quant_format_var.get(),
820
  custom_quant_map=self._custom_map_for_plan() or {},
821
  enable_q4_fallback=bool(self.q4_fallback_var.get()) and self.quant_format_var.get() not in ("q2_k", "q3_k"),
 
869
  cmd += ["--thermal-tilt", str(float(self.thermal_tilt_var.get()))]
870
  if self.pin_dc_var.get():
871
  cmd += ["--pin-dc"]
 
 
 
 
 
 
 
 
872
  cmd.append("--verbose")
873
  return " ".join(shlex.quote(part) for part in cmd)
874
 
 
932
  self._refresh_plan_view()
933
  self._update_cli_preview()
934
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
935
  def _refresh_plan_view(self) -> None:
936
  if self._reader is None:
937
  return
 
939
  scope_selected = self.mode_var.get() == "selected"
940
  n_q2, n_q3, n_q4, n_copy = 0, 0, 0, 0
941
  n_q1 = 0
942
+ planned_bytes = 0
 
943
  for ti in self._reader.tensors:
944
  tgt = self._plan_target(ti, chosen, scope_selected)
945
  if tgt == "Q2_K":
 
963
  planned_bytes += (ti.n_elements // QK1_0) * Q1_0_BLOCK_BYTES
964
  else:
965
  planned_bytes += ti.n_bytes
 
 
 
966
 
967
  if not self.tree.exists(ti.name):
968
  continue
 
980
  vals[6] = state_str
981
  self.tree.item(ti.name, tags=(tgt_label,), values=vals)
982
 
983
+ if planned_bytes >= 1024 ** 3:
984
+ planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
985
+ elif planned_bytes >= 1024 ** 2:
986
+ planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
987
+ else:
988
+ planned_text = f"{planned_bytes / 1024:.1f} KiB"
989
  scope_text = "selected" if scope_selected else "all"
990
  self.status_var.set(
991
  f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
 
1002
  plan_filt = self.plan_filter_var.get()
1003
  n_q2, n_q3, n_q4, n_copy = 0, 0, 0, 0
1004
  n_q1 = 0
1005
+ planned_bytes = 0
 
1006
  for ti in self._reader.tensors:
1007
  tgt = self._plan_target(ti, chosen, scope_selected)
1008
  if tgt == "Q2_K":
 
1026
  planned_bytes += (ti.n_elements // QK1_0) * Q1_0_BLOCK_BYTES
1027
  else:
1028
  planned_bytes += ti.n_bytes
 
 
 
1029
 
1030
  tgt_label = tgt if tgt else "Copy"
1031
  if plan_filt != "ALL" and tgt_label.upper() != plan_filt:
 
1067
  keep_selected = [n for n in chosen if self.tree.exists(n)]
1068
  if keep_selected:
1069
  self.tree.selection_set(keep_selected)
1070
+ if planned_bytes >= 1024 ** 3:
1071
+ planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
1072
+ elif planned_bytes >= 1024 ** 2:
1073
+ planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
1074
+ else:
1075
+ planned_text = f"{planned_bytes / 1024:.1f} KiB"
1076
  scope_text = "selected" if scope_selected else "all"
1077
  self.status_var.set(
1078
  f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
pipeline.py CHANGED
@@ -2,7 +2,6 @@
2
 
3
  Pipeline stages (mirroring the C engine, with V2 fixes):
4
 
5
- 0. self-describing per-superblock segmentation (opt-in, ``cfg.segment``);
6
  1. kurtosis-gated outlier clamp and batched GGML seeds;
7
  2. vectorised WLS superblock solve;
8
  3. factored candidate field + standalone factored floor;
@@ -73,8 +72,6 @@ class TensorStats:
73
  factor_floor_used: int
74
  candidate_floor_used: int
75
  therm_improved: int = 0
76
- segment_rounds: int = 0
77
- segment_flips: int = 0
78
 
79
 
80
  @dataclass(slots=True)
@@ -87,22 +84,10 @@ class QuantizedTensor:
87
  factor_objectives: np.ndarray
88
  config: HPCConfig
89
  stats: TensorStats
90
- segment_perm: np.ndarray | None = None
91
- segment_labels: np.ndarray | None = None
92
 
93
  def dequantize(self) -> np.ndarray:
94
  return np.concatenate([b.dequantize() for b in self.blocks])
95
 
96
- def dequantize_original(self) -> np.ndarray:
97
- """Consumer-side reconstruction: scatter dequantized slots back to
98
- original positions using the stored label channel (exact)."""
99
- if self.segment_perm is None:
100
- return self.dequantize()
101
- Xh = np.stack([b.dequantize() for b in self.blocks])
102
- out = np.empty_like(Xh)
103
- np.put_along_axis(out, self.segment_perm, Xh, axis=1)
104
- return out.ravel()
105
-
106
 
107
  def _phase2_wls(X, W, seeds, cfg: HPCConfig):
108
  n = X.shape[0]
@@ -879,39 +864,6 @@ class Q2KQuantizer:
879
  x = x.ravel()
880
  n_blocks = x.size // QK_K
881
 
882
- seg_perm = None
883
- seg_labels = None
884
- seg_rounds = 0
885
- seg_flips = 0
886
-
887
- if cfg.segment:
888
- from .segmentation import apply_order, q2k_proxy_cfg, segment_stage
889
-
890
- _emit(
891
- "Phase 0: Band-Major Segmentation & Lookup Table",
892
- 0,
893
- n_blocks,
894
- f"Building {cfg.segment_table_size}-entry LUT & assigning {n_blocks:,} superblocks (k={cfg.segment_k})",
895
- )
896
- X_p = x.reshape(n_blocks, QK_K)
897
- imp2d = (
898
- None
899
- if importance is None
900
- else np.asarray(importance, dtype=np.float32).ravel().reshape(n_blocks, QK_K)
901
- )
902
- clamp_val0 = float(seed_clamp_value(x, cfg))
903
- proxy = q2k_proxy_cfg(clamp_val0, cfg)
904
- seg_perm, seg_labels, seg_rounds = segment_stage(
905
- X_p, imp2d, cfg, proxy, max(2, int(cfg.segment_k))
906
- )
907
- X_p = apply_order(X_p, seg_perm).astype(np.float32)
908
- x = np.ascontiguousarray(X_p.ravel())
909
- if imp2d is not None:
910
- importance = np.ascontiguousarray(
911
- apply_order(imp2d, seg_perm).astype(np.float32).ravel()
912
- )
913
- X_p = None
914
-
915
  if cfg.device != "cpu":
916
  from .cuda_backend import cuda_is_available, quantize_cuda
917
 
@@ -920,7 +872,7 @@ class Q2KQuantizer:
920
  ):
921
  dev_str = "cuda" if cfg.device == "auto" else cfg.device
922
  res = quantize_cuda(
923
- x if seg_labels is not None else weights,
924
  importance,
925
  row_width,
926
  cfg,
@@ -928,17 +880,6 @@ class Q2KQuantizer:
928
  stop_event=stop_event,
929
  device=dev_str,
930
  )
931
- if seg_perm is not None:
932
- from .segmentation import band_labels
933
-
934
- n_chk = min(n_blocks, 256)
935
- Xh = np.stack([b.dequantize() for b in res.blocks[:n_chk]]).astype(np.float64)
936
- labels_slot = np.take_along_axis(seg_labels[:n_chk], seg_perm[:n_chk], axis=1)
937
- labels_rec = band_labels(Xh, max(2, int(cfg.segment_k)))
938
- res.stats.segment_rounds = seg_rounds
939
- res.stats.segment_flips = int(np.count_nonzero(labels_rec != labels_slot))
940
- res.segment_perm = seg_perm
941
- res.segment_labels = seg_labels
942
  if cfg.verbose:
943
  _report(res.stats)
944
  return res
@@ -1258,17 +1199,6 @@ class Q2KQuantizer:
1258
  else:
1259
  weighted += float(np.dot(W[i].astype(np.float64), e * e))
1260
 
1261
- if seg_perm is not None:
1262
- # informational: how many labels a channelless decoder would
1263
- # mis-derive from the stored slot values
1264
- from .segmentation import band_labels
1265
-
1266
- n_chk = min(n_blocks, 256)
1267
- Xh = np.stack([b.dequantize() for b in blocks[:n_chk]]).astype(np.float64)
1268
- labels_slot = np.take_along_axis(seg_labels[:n_chk], seg_perm[:n_chk], axis=1)
1269
- labels_rec = band_labels(Xh, max(2, int(cfg.segment_k)))
1270
- seg_flips = int(np.count_nonzero(labels_rec != labels_slot))
1271
-
1272
  rmse = float(np.sqrt(total_sse / x.size))
1273
  stats = TensorStats(
1274
  n_blocks=n_blocks,
@@ -1281,8 +1211,6 @@ class Q2KQuantizer:
1281
  factor_floor_used=factor_floor_used,
1282
  candidate_floor_used=candidate_floor_used,
1283
  therm_improved=therm_improved,
1284
- segment_rounds=seg_rounds,
1285
- segment_flips=seg_flips,
1286
  )
1287
  _emit(
1288
  "Phase 5: Tensor Complete",
@@ -1309,8 +1237,6 @@ class Q2KQuantizer:
1309
  factor_objectives=factor_objectives,
1310
  config=cfg,
1311
  stats=stats,
1312
- segment_perm=seg_perm,
1313
- segment_labels=seg_labels,
1314
  )
1315
  if cfg.verbose:
1316
  _report(stats)
@@ -1332,8 +1258,6 @@ def _stack_blocks(blocks):
1332
 
1333
  def _report(stats: TensorStats) -> None:
1334
  extra = f" therm={stats.therm_improved}" if stats.therm_improved else ""
1335
- if stats.segment_rounds:
1336
- extra += f" seg(rounds={stats.segment_rounds}, flips={stats.segment_flips})"
1337
  print(
1338
  f"Q2_K V2: blocks={stats.n_blocks} rmse={stats.rmse:.6e} "
1339
  f"rmse/sigma={stats.rmse_over_sigma:.5f} temp={stats.temperature:.3e} "
 
2
 
3
  Pipeline stages (mirroring the C engine, with V2 fixes):
4
 
 
5
  1. kurtosis-gated outlier clamp and batched GGML seeds;
6
  2. vectorised WLS superblock solve;
7
  3. factored candidate field + standalone factored floor;
 
72
  factor_floor_used: int
73
  candidate_floor_used: int
74
  therm_improved: int = 0
 
 
75
 
76
 
77
  @dataclass(slots=True)
 
84
  factor_objectives: np.ndarray
85
  config: HPCConfig
86
  stats: TensorStats
 
 
87
 
88
  def dequantize(self) -> np.ndarray:
89
  return np.concatenate([b.dequantize() for b in self.blocks])
90
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  def _phase2_wls(X, W, seeds, cfg: HPCConfig):
93
  n = X.shape[0]
 
864
  x = x.ravel()
865
  n_blocks = x.size // QK_K
866
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
  if cfg.device != "cpu":
868
  from .cuda_backend import cuda_is_available, quantize_cuda
869
 
 
872
  ):
873
  dev_str = "cuda" if cfg.device == "auto" else cfg.device
874
  res = quantize_cuda(
875
+ weights,
876
  importance,
877
  row_width,
878
  cfg,
 
880
  stop_event=stop_event,
881
  device=dev_str,
882
  )
 
 
 
 
 
 
 
 
 
 
 
883
  if cfg.verbose:
884
  _report(res.stats)
885
  return res
 
1199
  else:
1200
  weighted += float(np.dot(W[i].astype(np.float64), e * e))
1201
 
 
 
 
 
 
 
 
 
 
 
 
1202
  rmse = float(np.sqrt(total_sse / x.size))
1203
  stats = TensorStats(
1204
  n_blocks=n_blocks,
 
1211
  factor_floor_used=factor_floor_used,
1212
  candidate_floor_used=candidate_floor_used,
1213
  therm_improved=therm_improved,
 
 
1214
  )
1215
  _emit(
1216
  "Phase 5: Tensor Complete",
 
1237
  factor_objectives=factor_objectives,
1238
  config=cfg,
1239
  stats=stats,
 
 
1240
  )
1241
  if cfg.verbose:
1242
  _report(stats)
 
1258
 
1259
  def _report(stats: TensorStats) -> None:
1260
  extra = f" therm={stats.therm_improved}" if stats.therm_improved else ""
 
 
1261
  print(
1262
  f"Q2_K V2: blocks={stats.n_blocks} rmse={stats.rmse:.6e} "
1263
  f"rmse/sigma={stats.rmse_over_sigma:.5f} temp={stats.temperature:.3e} "
q3_k.py CHANGED
@@ -983,17 +983,12 @@ def quantize_tensor_q3_k(
983
  importance: np.ndarray | None = None,
984
  cfg: HPCConfig | None = None,
985
  chunk_blocks: int | None = None,
986
- return_labels: bool = False,
987
- ):
988
  """Quantize a tensor to GGML Q3_K using the full HPC V2 pipeline.
989
 
990
  ``chunk_blocks`` (256-weight super-blocks per chunk) defaults to
991
  ``Q3_K_CHUNK_BLOCKS_CUDA`` on the GPU path (same weights-per-chunk as the
992
  Q4_0 reference) and ``Q3_K_CHUNK_BLOCKS_CPU`` on the CPU path.
993
-
994
- With ``return_labels=True`` returns ``(payload, n_blocks, rmse, labels)``
995
- where ``labels`` is the segmentation label channel (one band id per
996
- original position, or None when segmentation is off).
997
  """
998
  cfg = cfg or HPCConfig()
999
  x = np.asarray(weights, dtype=np.float32).ravel()
@@ -1010,22 +1005,6 @@ def quantize_tensor_q3_k(
1010
  else:
1011
  W_raw = None
1012
 
1013
- if cfg.segment:
1014
- from .segmentation import apply_order, band_labels, q3k_proxy, segment_stage
1015
-
1016
- seg_order, seg_labels, seg_rounds = segment_stage(
1017
- X, W_raw, cfg, q3k_proxy, max(2, int(cfg.segment_k))
1018
- )
1019
- X = np.ascontiguousarray(apply_order(X.astype(np.float64), seg_order)).astype(np.float32)
1020
- if W_raw is not None:
1021
- W_raw = np.ascontiguousarray(
1022
- apply_order(W_raw.astype(np.float64), seg_order)
1023
- ).astype(np.float32)
1024
- else:
1025
- seg_order = None
1026
- seg_labels = None
1027
- seg_rounds = 0
1028
-
1029
  cuda_ok = cfg.device != "cpu" and cuda_is_available()
1030
  use_cuda = cuda_ok and (
1031
  cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
@@ -1062,22 +1041,4 @@ def quantize_tensor_q3_k(
1062
  total_sse += sse_b
1063
 
1064
  rmse = float(np.sqrt(total_sse / x.size))
1065
-
1066
- if cfg.segment:
1067
- n_chk = min(n_blocks, 256)
1068
- raw_chk = b"".join(chunks)[: n_chk * Q3_K_BLOCK_BYTES]
1069
- xh = np.asarray(dequantize_q3_k_bytes(raw_chk, n_chk), dtype=np.float64).reshape(
1070
- n_chk, QK3_K
1071
- )
1072
- labels_slot = np.take_along_axis(seg_labels[:n_chk], seg_order[:n_chk], axis=1)
1073
- labels_rec = band_labels(xh, max(2, int(cfg.segment_k)))
1074
- seg_flips = int(np.count_nonzero(labels_rec != labels_slot))
1075
- _log.info(
1076
- "Q3_K segmentation: rounds=%d channelless flips=%d rmse=%.6e",
1077
- seg_rounds, seg_flips, rmse,
1078
- )
1079
-
1080
- payload = b"".join(chunks)
1081
- if return_labels:
1082
- return payload, n_blocks, rmse, seg_labels
1083
- return payload, n_blocks, rmse
 
983
  importance: np.ndarray | None = None,
984
  cfg: HPCConfig | None = None,
985
  chunk_blocks: int | None = None,
986
+ ) -> tuple[bytes, int, float]:
 
987
  """Quantize a tensor to GGML Q3_K using the full HPC V2 pipeline.
988
 
989
  ``chunk_blocks`` (256-weight super-blocks per chunk) defaults to
990
  ``Q3_K_CHUNK_BLOCKS_CUDA`` on the GPU path (same weights-per-chunk as the
991
  Q4_0 reference) and ``Q3_K_CHUNK_BLOCKS_CPU`` on the CPU path.
 
 
 
 
992
  """
993
  cfg = cfg or HPCConfig()
994
  x = np.asarray(weights, dtype=np.float32).ravel()
 
1005
  else:
1006
  W_raw = None
1007
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1008
  cuda_ok = cfg.device != "cpu" and cuda_is_available()
1009
  use_cuda = cuda_ok and (
1010
  cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
 
1041
  total_sse += sse_b
1042
 
1043
  rmse = float(np.sqrt(total_sse / x.size))
1044
+ return b"".join(chunks), n_blocks, rmse
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
q4_0.py CHANGED
@@ -28,8 +28,6 @@ per 18-byte block = 4.5 bpw):
28
  from __future__ import annotations
29
 
30
  from math import ceil
31
- import logging
32
-
33
  import numpy as np
34
 
35
  try:
@@ -50,8 +48,6 @@ QK4_0 = 32
50
  Q4_0_BLOCK_BYTES = 18
51
  Q4_N_CAND = 24
52
  Q4_N_STATES = 6
53
-
54
- _log = logging.getLogger(__name__)
55
  Q4_N_LEVELS = 16
56
 
57
 
@@ -587,16 +583,6 @@ def quantize_tensor_q4_0(
587
  else:
588
  W_raw = None
589
 
590
- if cfg.segment:
591
- # Q4_0's unit block (32 weights, one scale+min) has no per-band
592
- # sub-scale dof to align, position-ascending k=1 layout is the
593
- # identity permutation, and the permutation channel would pay 8
594
- # bits per weight for nothing. Explicit no-op for now.
595
- _log.info(
596
- "Q4_0 segmentation disabled: unit blocks (d, min) have no band dof "
597
- "to align (k=1 layout is the identity)"
598
- )
599
-
600
  use_cuda = cfg.device != "cpu" and cuda_is_available() and (
601
  cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
602
  )
 
28
  from __future__ import annotations
29
 
30
  from math import ceil
 
 
31
  import numpy as np
32
 
33
  try:
 
48
  Q4_0_BLOCK_BYTES = 18
49
  Q4_N_CAND = 24
50
  Q4_N_STATES = 6
 
 
51
  Q4_N_LEVELS = 16
52
 
53
 
 
583
  else:
584
  W_raw = None
585
 
 
 
 
 
 
 
 
 
 
 
586
  use_cuda = cfg.device != "cpu" and cuda_is_available() and (
587
  cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
588
  )