CompressedGemma commited on
Commit
6186af4
·
verified ·
1 Parent(s): 4840bdd

Upload 14 files

Browse files
Files changed (2) hide show
  1. gguf.py +37 -1
  2. pipeline.py +127 -3
gguf.py CHANGED
@@ -377,6 +377,7 @@ def write_quantized_gguf(
377
  limit: int = 0,
378
  verbose: bool = True,
379
  progress_callback=None,
 
380
  stop_event=None,
381
  ) -> dict[str, float]:
382
  """Quantize a source GGUF with the V2 engine and emit a valid GGUF.
@@ -469,13 +470,36 @@ def write_quantized_gguf(
469
  if target > fout.tell():
470
  fout.write(b"\x00" * (target - fout.tell()))
471
  if plan[idx]:
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  x, row = reader.read_tensor(ti.name)
473
  imp = None
474
  if imat is not None:
475
  raw_imp = lookup_imatrix(imat, ti.name)
476
  if raw_imp is not None:
477
  imp = expand_importance(raw_imp, x.size, row)
478
- res = quantizer.quantize(x, importance=imp, row_width=row)
 
 
 
 
 
 
 
 
 
 
479
  payload = blocks_to_bytes(res.scales, res.qs, res.dm)
480
  if len(payload) != out_size:
481
  raise RuntimeError(f"{ti.name}: Q2_K payload size mismatch")
@@ -498,6 +522,18 @@ def write_quantized_gguf(
498
  imp is not None,
499
  )
500
  else:
 
 
 
 
 
 
 
 
 
 
 
 
501
  reader.copy_tensor_raw_to(ti.name, fout)
502
  if verbose and idx % 25 == 0:
503
  print(f" copy {ti.name}")
 
377
  limit: int = 0,
378
  verbose: bool = True,
379
  progress_callback=None,
380
+ stage_callback=None,
381
  stop_event=None,
382
  ) -> dict[str, float]:
383
  """Quantize a source GGUF with the V2 engine and emit a valid GGUF.
 
470
  if target > fout.tell():
471
  fout.write(b"\x00" * (target - fout.tell()))
472
  if plan[idx]:
473
+ has_imat = imat is not None and lookup_imatrix(imat, ti.name) is not None
474
+ if stage_callback is not None:
475
+ stage_callback(
476
+ idx + 1,
477
+ len(out_infos),
478
+ ti,
479
+ {
480
+ "phase": f"Reading & Dequantizing Source ({ti.type_name})",
481
+ "done": 0,
482
+ "total": ti.n_elements // QK_K,
483
+ "detail": f"dims={ti.dims} elements={ti.n_elements:,} ({ti.n_bytes / 1048576:.2f} MB) imatrix={'yes' if has_imat else 'no'}",
484
+ },
485
+ )
486
  x, row = reader.read_tensor(ti.name)
487
  imp = None
488
  if imat is not None:
489
  raw_imp = lookup_imatrix(imat, ti.name)
490
  if raw_imp is not None:
491
  imp = expand_importance(raw_imp, x.size, row)
492
+ res = quantizer.quantize(
493
+ x,
494
+ importance=imp,
495
+ row_width=row,
496
+ status_callback=(
497
+ (lambda ev, _i=idx + 1, _ti=ti: stage_callback(_i, len(out_infos), _ti, ev))
498
+ if stage_callback is not None
499
+ else None
500
+ ),
501
+ stop_event=stop_event,
502
+ )
503
  payload = blocks_to_bytes(res.scales, res.qs, res.dm)
504
  if len(payload) != out_size:
505
  raise RuntimeError(f"{ti.name}: Q2_K payload size mismatch")
 
522
  imp is not None,
523
  )
524
  else:
525
+ if stage_callback is not None:
526
+ stage_callback(
527
+ idx + 1,
528
+ len(out_infos),
529
+ ti,
530
+ {
531
+ "phase": f"Passthrough Copy ({ti.type_name})",
532
+ "done": 1,
533
+ "total": 1,
534
+ "detail": f"dims={ti.dims} ({ti.n_bytes / 1048576:.2f} MB)",
535
+ },
536
+ )
537
  reader.copy_tensor_raw_to(ti.name, fout)
538
  if verbose and idx % 25 == 0:
539
  print(f" copy {ti.name}")
pipeline.py CHANGED
@@ -17,6 +17,7 @@ from __future__ import annotations
17
 
18
  from dataclasses import dataclass
19
  from math import ceil
 
20
 
21
  import numpy as np
22
 
@@ -413,7 +414,25 @@ class Q2KQuantizer:
413
  weights: np.ndarray,
414
  importance: np.ndarray | None = None,
415
  row_width: int | None = None,
 
 
416
  ) -> QuantizedTensor:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  cfg = self.config
418
  x = np.asarray(weights, dtype=np.float32)
419
  if x.size == 0:
@@ -436,13 +455,34 @@ class Q2KQuantizer:
436
  else:
437
  W = None
438
 
 
 
439
  clamp_val = seed_clamp_value(x, cfg)
 
 
 
 
 
 
 
440
  seeds = build_seeds(X, W, cfg, clamp_val)
 
 
 
 
 
 
 
 
441
  base_d, base_m = _phase2_wls(X, W, seeds, clamp_val)
442
 
443
  candidate_errors = np.full((n_blocks, TOTAL_CANDIDATES), np.inf, dtype=np.float32)
444
  standalone: list[FactorResult] = []
 
 
 
445
  for i in range(n_blocks):
 
446
  wi = None if W is None else W[i]
447
  candidate_errors[i] = factor_candidates(
448
  X[i],
@@ -453,13 +493,48 @@ class Q2KQuantizer:
453
  base_m[i],
454
  cfg,
455
  )
456
- standalone.append(factor_only_solve(X[i], wi, cfg))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
 
 
 
 
 
 
 
 
 
458
  best, temperature, _ = _phase3_select(candidate_errors, cfg)
459
  carry = _compute_dc_carry(X, seeds, best, base_d, base_m, cfg, row_width)
 
 
 
 
 
 
 
 
460
 
461
  at_slot: list[FactorResult] = []
462
  for i in range(n_blocks):
 
463
  wi = None if W is None else W[i]
464
  d16, m16 = candidate_pair(base_d[i], base_m[i], best[i])
465
  at_slot.append(
@@ -482,7 +557,11 @@ class Q2KQuantizer:
482
  blocks: list[Q2KBlock] = []
483
  factor_floor_used = 0
484
  candidate_floor_used = 0
 
 
 
485
  for i in range(n_blocks):
 
486
  wi = None if W is None else W[i]
487
  d, m, ls, lm, codes, obj, sse = _assemble_block(
488
  X[i], wi, seeds, base_d[i], base_m[i], best[i], carry[i], cfg
@@ -517,9 +596,42 @@ class Q2KQuantizer:
517
  obj, sse = fobj, fsse
518
  factor_floor_used += 1
519
 
520
- blocks.append(make_block(d, m, ls, lm, codes))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
  if cfg.apply_dc_carry and (cfg.dc_lambda > 0.0 or cfg.dc_decay > 0.0):
 
 
 
 
 
 
 
 
 
523
  blocks = _apply_dc_nudge(X, W, blocks, cfg, row_width)
524
 
525
  total_sse = 0.0
@@ -532,7 +644,6 @@ class Q2KQuantizer:
532
  else:
533
  weighted += float(np.dot(W[i].astype(np.float64), e * e))
534
 
535
- sigma = float(np.sqrt(np.mean(x.astype(np.float64) ** 2)))
536
  rmse = float(np.sqrt(total_sse / x.size))
537
  stats = TensorStats(
538
  n_blocks=n_blocks,
@@ -545,6 +656,19 @@ class Q2KQuantizer:
545
  factor_floor_used=factor_floor_used,
546
  candidate_floor_used=candidate_floor_used,
547
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  scales, qs, dm = _stack_blocks(blocks)
549
  factor_objectives = np.array([r.objective for r in standalone], dtype=np.float64)
550
  result = QuantizedTensor(
 
17
 
18
  from dataclasses import dataclass
19
  from math import ceil
20
+ import time
21
 
22
  import numpy as np
23
 
 
414
  weights: np.ndarray,
415
  importance: np.ndarray | None = None,
416
  row_width: int | None = None,
417
+ status_callback=None,
418
+ stop_event=None,
419
  ) -> QuantizedTensor:
420
+ def _emit(phase: str, done: int, total: int, detail: str, **extra) -> None:
421
+ if status_callback is not None:
422
+ status_callback(
423
+ {
424
+ "phase": phase,
425
+ "done": done,
426
+ "total": total,
427
+ "detail": detail,
428
+ **extra,
429
+ }
430
+ )
431
+
432
+ def _check_stop() -> None:
433
+ if stop_event is not None and stop_event.is_set():
434
+ raise InterruptedError("Quantization cancelled by user")
435
+
436
  cfg = self.config
437
  x = np.asarray(weights, dtype=np.float32)
438
  if x.size == 0:
 
455
  else:
456
  W = None
457
 
458
+ sigma = float(np.sqrt(np.mean(x.astype(np.float64) ** 2)))
459
+ _check_stop()
460
  clamp_val = seed_clamp_value(x, cfg)
461
+ _emit(
462
+ "Phase 1: Kurtosis Clamp & Batched GGML Seeds",
463
+ 0,
464
+ n_blocks,
465
+ f"blocks={n_blocks} sigma={sigma:.5f} clamp={clamp_val:.5f} imatrix={'yes' if W is not None else 'no'}",
466
+ sigma=sigma,
467
+ )
468
  seeds = build_seeds(X, W, cfg, clamp_val)
469
+ _check_stop()
470
+ _emit(
471
+ "Phase 2a: Vectorized Superblock WLS",
472
+ 0,
473
+ n_blocks,
474
+ f"Solving 5-iteration WLS across {n_blocks} superblocks",
475
+ sigma=sigma,
476
+ )
477
  base_d, base_m = _phase2_wls(X, W, seeds, clamp_val)
478
 
479
  candidate_errors = np.full((n_blocks, TOTAL_CANDIDATES), np.inf, dtype=np.float32)
480
  standalone: list[FactorResult] = []
481
+ t_cand = time.time()
482
+ last_emit = 0.0
483
+ step_report = max(1, min(32, n_blocks // 20 or 1))
484
  for i in range(n_blocks):
485
+ _check_stop()
486
  wi = None if W is None else W[i]
487
  candidate_errors[i] = factor_candidates(
488
  X[i],
 
493
  base_m[i],
494
  cfg,
495
  )
496
+ fac_res = factor_only_solve(X[i], wi, cfg)
497
+ standalone.append(fac_res)
498
+ now = time.time()
499
+ if (i + 1) % step_report == 0 or (i + 1) == n_blocks or (now - last_emit) >= 0.25:
500
+ last_emit = now
501
+ elapsed = max(now - t_cand, 1.0e-6)
502
+ rate = (i + 1) / elapsed
503
+ eta = (n_blocks - (i + 1)) / max(rate, 1.0e-9)
504
+ _emit(
505
+ "Phase 2b: Analog-Guided Factored Candidate Field",
506
+ i + 1,
507
+ n_blocks,
508
+ f"blk {i+1}/{n_blocks} ({rate:.1f} blk/s, ETA {eta:.1f}s) "
509
+ f"d={float(fac_res.d):.5f} dmin={float(fac_res.dmin):.5f} "
510
+ f"obj={fac_res.objective:.5e} starts={fac_res.starts}",
511
+ rate=rate,
512
+ eta=eta,
513
+ sigma=sigma,
514
+ )
515
 
516
+ _check_stop()
517
+ _emit(
518
+ "Phase 3: 6-State Sieve & 36-State Viterbi DP",
519
+ 0,
520
+ n_blocks,
521
+ f"Running Sieve + 36-state Viterbi sequence optimization ({cfg.optimizer.upper()})",
522
+ sigma=sigma,
523
+ )
524
  best, temperature, _ = _phase3_select(candidate_errors, cfg)
525
  carry = _compute_dc_carry(X, seeds, best, base_d, base_m, cfg, row_width)
526
+ _emit(
527
+ "Phase 3.9: Viterbi Path & Rolling DC Carry",
528
+ n_blocks,
529
+ n_blocks,
530
+ f"Boltzmann temp={temperature:.4e}, max |DC carry|={float(np.max(np.abs(carry))):.4e}",
531
+ temperature=temperature,
532
+ sigma=sigma,
533
+ )
534
 
535
  at_slot: list[FactorResult] = []
536
  for i in range(n_blocks):
537
+ _check_stop()
538
  wi = None if W is None else W[i]
539
  d16, m16 = candidate_pair(base_d[i], base_m[i], best[i])
540
  at_slot.append(
 
557
  blocks: list[Q2KBlock] = []
558
  factor_floor_used = 0
559
  candidate_floor_used = 0
560
+ running_sse = 0.0
561
+ t_asm = time.time()
562
+ last_emit = 0.0
563
  for i in range(n_blocks):
564
+ _check_stop()
565
  wi = None if W is None else W[i]
566
  d, m, ls, lm, codes, obj, sse = _assemble_block(
567
  X[i], wi, seeds, base_d[i], base_m[i], best[i], carry[i], cfg
 
596
  obj, sse = fobj, fsse
597
  factor_floor_used += 1
598
 
599
+ blk_obj = make_block(d, m, ls, lm, codes)
600
+ blocks.append(blk_obj)
601
+ running_sse += blk_obj.error(X[i])
602
+ now = time.time()
603
+ if (i + 1) % step_report == 0 or (i + 1) == n_blocks or (now - last_emit) >= 0.25:
604
+ last_emit = now
605
+ elapsed = max(now - t_asm, 1.0e-6)
606
+ rate = (i + 1) / elapsed
607
+ eta = (n_blocks - (i + 1)) / max(rate, 1.0e-9)
608
+ cur_rmse = float(np.sqrt(running_sse / ((i + 1) * QK_K)))
609
+ _emit(
610
+ "Phase 4: Sub-block Sieve + ULP + Hadamard Assembly",
611
+ i + 1,
612
+ n_blocks,
613
+ f"blk {i+1}/{n_blocks} ({rate:.1f} blk/s, ETA {eta:.1f}s) "
614
+ f"rmse={cur_rmse:.6e} rmse/sigma={cur_rmse/max(sigma, 1e-15):.4f} "
615
+ f"floors(cand={candidate_floor_used}, fac={factor_floor_used})",
616
+ rmse=cur_rmse,
617
+ sigma=sigma,
618
+ temperature=temperature,
619
+ cand_floors=candidate_floor_used,
620
+ fac_floors=factor_floor_used,
621
+ rate=rate,
622
+ eta=eta,
623
+ )
624
 
625
  if cfg.apply_dc_carry and (cfg.dc_lambda > 0.0 or cfg.dc_decay > 0.0):
626
+ _check_stop()
627
+ _emit(
628
+ "Phase 4.8: Sequential Row-Aware DC Residual Nudge",
629
+ n_blocks,
630
+ n_blocks,
631
+ f"Cancelling cumulative row DC residuals (row_width={row_width or QK_K})",
632
+ sigma=sigma,
633
+ temperature=temperature,
634
+ )
635
  blocks = _apply_dc_nudge(X, W, blocks, cfg, row_width)
636
 
637
  total_sse = 0.0
 
644
  else:
645
  weighted += float(np.dot(W[i].astype(np.float64), e * e))
646
 
 
647
  rmse = float(np.sqrt(total_sse / x.size))
648
  stats = TensorStats(
649
  n_blocks=n_blocks,
 
656
  factor_floor_used=factor_floor_used,
657
  candidate_floor_used=candidate_floor_used,
658
  )
659
+ _emit(
660
+ "Phase 5: Tensor Complete",
661
+ n_blocks,
662
+ n_blocks,
663
+ f"Done: blocks={n_blocks} rmse={rmse:.6e} rmse/sigma={stats.rmse_over_sigma:.5f} "
664
+ f"wSSE={weighted:.5e} temp={temperature:.3e} "
665
+ f"floors(cand={candidate_floor_used}, fac={factor_floor_used})",
666
+ rmse=rmse,
667
+ sigma=sigma,
668
+ temperature=temperature,
669
+ cand_floors=candidate_floor_used,
670
+ fac_floors=factor_floor_used,
671
+ )
672
  scales, qs, dm = _stack_blocks(blocks)
673
  factor_objectives = np.array([r.objective for r in standalone], dtype=np.float64)
674
  result = QuantizedTensor(