CompressedGemma commited on
Commit
4856584
·
verified ·
1 Parent(s): bc08931

Super small quants

Browse files
Files changed (1) hide show
  1. hexstate_requantize.py +50 -23
hexstate_requantize.py CHANGED
@@ -643,6 +643,26 @@ def is_attention_tensor(name):
643
  return False
644
 
645
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  def q2k_row_compatible(n_dims, dims):
647
  return n_dims >= 2 and bool(dims) and int(dims[0]) % QK_K == 0
648
 
@@ -683,12 +703,11 @@ def should_quantize(name, n_dims, dims, tied_embeddings=False):
683
  - ffn_gate_inp — MoE routing gate
684
  - layer_output_scale — per-layer scaling factor (scalar)
685
  - altup, laurel — small Gemma-specific tensors
686
- - token_embd.weight / output.weight — always excluded here.
687
- When embeddings are TIED, main() routes token_embd.weight to
688
- Q8_0 (HPC sieve pipeline) instead: the same tensor serves as both
689
- embedding lookup AND LM head, and Q2_K/Q4_0 there destroys logit
690
- precision → looping / repetitive generation. --keep-embd keeps
691
- it at source precision instead.
692
  """
693
  n_elements = 1
694
  for d in dims:
@@ -705,20 +724,25 @@ def should_quantize(name, n_dims, dims, tied_embeddings=False):
705
  return False
706
  if 'layer_output_scale' in name:
707
  return False
708
- # Embedding table — this is a lookup, not a matmul; Q2_K destroys
709
- # token distinctions. Keep at source precision (F16/BF16).
710
- if 'token_embd' in name:
711
- return False
712
- # LM head output projection — logit precision is critical for generation.
713
- # (When tied with embeddings, this is the same tensor and also skipped above.)
714
- if name == 'output.weight':
715
- return False
716
- # DeltaNet state-space parameters — keep at full precision
717
- if 'ssm_a' in name or 'A_log' in name:
718
  return False
719
  if 'ssm_dt' in name or 'dt_bias' in name:
720
  return False
721
- if 'ssm_conv1d' in name or 'conv1d.weight' in name:
 
 
 
 
 
722
  return False
723
  # When embeddings are tied, token_embd.weight doubles as the output
724
  # projection (LM head). It gets routed to Q4_0 in the quant plan
@@ -881,8 +905,11 @@ def main():
881
  else:
882
  will_quant = False; total_keep += 1
883
  print(f" Q2ALL→KEEP (row width not block-aligned): {ti['name']}")
884
- elif is_attention_tensor(ti['name']) and q4_row_compatible(ti['n_dims'], ti['dims']):
885
- will_quant = 'ATTN_Q4'; total_attn += 1
 
 
 
886
  elif q2k_row_compatible(ti['n_dims'], ti['dims']):
887
  will_quant = True; total_quant += 1
888
  elif q4_row_compatible(ti['n_dims'], ti['dims']):
@@ -920,12 +947,12 @@ def main():
920
  n_blocks = ti['n_elements'] // 32
921
  out_size = n_blocks * 34
922
  print(f" [EMBD→Q8_0·Sieve] {ti['name']} ({ti['n_elements']:,} elements)")
923
- elif quant_plan[i] == 'ATTN_Q4':
924
  # Attention tensor → Q4_0 HPC (4.5 bpw)
925
  out_type = GGML_TYPE_Q4_0
926
  n_blocks = (ti['n_elements'] + 31) // 32
927
  out_size = n_blocks * 18
928
- print(f" [ATTN→Q4_0·HPC] {ti['name']} ({ti['n_elements']} elements)")
929
  elif quant_plan[i] == 'Q4_0':
930
  out_type = GGML_TYPE_Q4_0
931
  n_blocks = ti['n_elements'] // 32
@@ -1151,7 +1178,7 @@ def main():
1151
  quant_count += 1
1152
  total_quant_bytes += n_blocks_q8 * 34
1153
 
1154
- elif quant_plan[i] in ('Q4_0', 'ATTN_Q4'):
1155
  # ── Q4_0 quantization (fallback or attention HPC) ──
1156
  if ti['type'] == GGML_TYPE_BF16:
1157
  f32 = bf16_to_f32(raw_data, ti['n_elements'])
@@ -1171,7 +1198,7 @@ def main():
1171
  n_blocks_q4 = n_el // 32
1172
 
1173
  # Use HPC for attention tensors if available
1174
- if quant_plan[i] == 'ATTN_Q4' and use_hpc and hasattr(_HEXSTATE_LIB, 'hexstate_quantize_tensor_q4_0_hpc'):
1175
  output_buf = np.zeros(n_blocks_q4 * 18, dtype=np.uint8)
1176
  error = ctypes.c_float(0.0)
1177
  f32_c = np.ascontiguousarray(f32, dtype=np.float32)
 
643
  return False
644
 
645
 
646
+ def is_q4_tensor(name):
647
+ """Tensors demoted to Q4_0 (HPC sieve) while Q2_K tensors stay Q2_K.
648
+
649
+ The full-precision leftovers: LM head / embedding tables plus
650
+ SSM-side weights (ssm_alpha mirrors ssm_beta, which already ships
651
+ Q2_K; ssm_conv1d kernels are small dense 2D projections).
652
+ Attention/FFN are NOT matched here — they keep their Q2_K plan.
653
+ NOTE: 'output.weight' is exact-matched so 'attn_output.weight'
654
+ never matches.
655
+ """
656
+ if name == 'output.weight' or name.endswith('.output.weight'):
657
+ return True
658
+ if name == 'token_embd.weight' or '.token_embd.weight' in name:
659
+ return True
660
+ for pat in ('ssm_alpha.weight', 'ssm_conv1d.weight', 'conv1d.weight'):
661
+ if pat in name:
662
+ return True
663
+ return False
664
+
665
+
666
  def q2k_row_compatible(n_dims, dims):
667
  return n_dims >= 2 and bool(dims) and int(dims[0]) % QK_K == 0
668
 
 
703
  - ffn_gate_inp — MoE routing gate
704
  - layer_output_scale — per-layer scaling factor (scalar)
705
  - altup, laurel — small Gemma-specific tensors
706
+ - token_embd.weight / output.weight — demoted to Q4_0 in main()
707
+ (is_q4_tensor). When embeddings are TIED, main() routes
708
+ token_embd.weight to Q8_0 (HPC sieve pipeline) instead: the same
709
+ tensor serves as both embedding lookup AND LM head. --keep-embd
710
+ keeps it at source precision instead.
 
711
  """
712
  n_elements = 1
713
  for d in dims:
 
724
  return False
725
  if 'layer_output_scale' in name:
726
  return False
727
+ # Embedding table / LM head — demoted to Q4_0 in main()
728
+ # (is_q4_tensor), NOT kept at source precision. (When embeddings are
729
+ # TIED, main() routes token_embd.weight to Q8_0 instead — that branch
730
+ # runs before should_quantize is consulted.)
731
+ # DeltaNet state-space parameters — keep truly scalar/vector ones
732
+ # at full precision. NOTE: 'ssm_a' must match the standalone 1D tensor
733
+ # only ('blk.N.ssm_a'), NOT 'ssm_alpha' (contains 'ssm_a' as a
734
+ # substring). ssm_alpha is a regular 2D projection weight and is
735
+ # quantizable — it mirrors ssm_beta, which already ships Q2_K.
736
+ if 'ssm_a' in name.split('.') or 'A_log' in name:
737
  return False
738
  if 'ssm_dt' in name or 'dt_bias' in name:
739
  return False
740
+ # ssm_conv1d kernels are quantizable ONLY when their row width is a
741
+ # multiple of the quant block size: GGUF quant blocks tile along dim0,
742
+ # so e.g. dims [4, 10240] can never be Q4_0/Q8_0/Q2_K regardless of
743
+ # total-element divisibility (llama.cpp rejects such files at load).
744
+ if ('ssm_conv1d' in name or 'conv1d.weight' in name) \
745
+ and (not dims or dims[0] % 32 != 0):
746
  return False
747
  # When embeddings are tied, token_embd.weight doubles as the output
748
  # projection (LM head). It gets routed to Q4_0 in the quant plan
 
905
  else:
906
  will_quant = False; total_keep += 1
907
  print(f" Q2ALL→KEEP (row width not block-aligned): {ti['name']}")
908
+ elif is_q4_tensor(ti['name']) and q4_row_compatible(ti['n_dims'], ti['dims']):
909
+ # Q4_0 path (HPC sieve). dim0 — not just total n — must be
910
+ # block-aligned: GGUF quants tile along rows and llama.cpp
911
+ # refuses to load otherwise.
912
+ will_quant = 'Q4_HPC'; total_attn += 1
913
  elif q2k_row_compatible(ti['n_dims'], ti['dims']):
914
  will_quant = True; total_quant += 1
915
  elif q4_row_compatible(ti['n_dims'], ti['dims']):
 
947
  n_blocks = ti['n_elements'] // 32
948
  out_size = n_blocks * 34
949
  print(f" [EMBD→Q8_0·Sieve] {ti['name']} ({ti['n_elements']:,} elements)")
950
+ elif quant_plan[i] == 'Q4_HPC':
951
  # Attention tensor → Q4_0 HPC (4.5 bpw)
952
  out_type = GGML_TYPE_Q4_0
953
  n_blocks = (ti['n_elements'] + 31) // 32
954
  out_size = n_blocks * 18
955
+ print(f" [Q4_0·HPC] {ti['name']} ({ti['n_elements']} elements)")
956
  elif quant_plan[i] == 'Q4_0':
957
  out_type = GGML_TYPE_Q4_0
958
  n_blocks = ti['n_elements'] // 32
 
1178
  quant_count += 1
1179
  total_quant_bytes += n_blocks_q8 * 34
1180
 
1181
+ elif quant_plan[i] in ('Q4_0', 'Q4_HPC'):
1182
  # ── Q4_0 quantization (fallback or attention HPC) ──
1183
  if ti['type'] == GGML_TYPE_BF16:
1184
  f32 = bf16_to_f32(raw_data, ti['n_elements'])
 
1198
  n_blocks_q4 = n_el // 32
1199
 
1200
  # Use HPC for attention tensors if available
1201
+ if quant_plan[i] == 'Q4_HPC' and use_hpc and hasattr(_HEXSTATE_LIB, 'hexstate_quantize_tensor_q4_0_hpc'):
1202
  output_buf = np.zeros(n_blocks_q4 * 18, dtype=np.uint8)
1203
  error = ctypes.c_float(0.0)
1204
  f32_c = np.ascontiguousarray(f32, dtype=np.float32)