--analog-imatrix: Reduce error in output by 15%
Browse files- hexstate_quantize.c +0 -0
- hexstate_requantize.py +204 -7
hexstate_quantize.c
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
hexstate_requantize.py
CHANGED
|
@@ -10,6 +10,14 @@ This bypasses the tokenizer parsing problem entirely β the source GGUF
|
|
| 10 |
|
| 11 |
Usage:
|
| 12 |
python3 hexstate_requantize.py input.gguf output.gguf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
"""
|
| 14 |
|
| 15 |
import struct
|
|
@@ -53,6 +61,22 @@ def _load_hexstate_lib():
|
|
| 53 |
ctypes.c_int, # verbose
|
| 54 |
]
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
lib.hexstate_q2k_block_bytes.restype = ctypes.c_int
|
| 57 |
lib.hexstate_q2k_block_bytes.argtypes = []
|
| 58 |
lib.hexstate_q2k_block_elements.restype = ctypes.c_int
|
|
@@ -124,6 +148,121 @@ def _skip_gguf_kv_value(f, vtype):
|
|
| 124 |
f.read(sz)
|
| 125 |
|
| 126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
def read_imatrix(path):
|
| 128 |
"""Read llama.cpp importance matrix file (GGUF or legacy .dat format).
|
| 129 |
|
|
@@ -734,6 +873,27 @@ def main():
|
|
| 734 |
print(f" WARNING: imatrix file not found: {imat_path}")
|
| 735 |
break
|
| 736 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 737 |
# Check for HPC C library
|
| 738 |
use_hpc = _load_hexstate_lib() is not None
|
| 739 |
|
|
@@ -1057,7 +1217,14 @@ def main():
|
|
| 1057 |
total_quant_bytes = 0
|
| 1058 |
total_keep_bytes = 0
|
| 1059 |
total_rmse = 0.0
|
| 1060 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1061 |
q2k_tensor_count = 0
|
| 1062 |
|
| 1063 |
for i, ti in enumerate(tensor_infos):
|
|
@@ -1228,7 +1395,29 @@ def main():
|
|
| 1228 |
imat_full = np.tile(iw, n_rows)[:ti['n_elements']]
|
| 1229 |
|
| 1230 |
n_el = ti['n_elements']
|
| 1231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1232 |
# Small tensor β single HPC pass
|
| 1233 |
q2k_data, n_blocks = quantize_tensor_q2k_hpc(f32, opt_mode=2, importance=imat_full)
|
| 1234 |
elif use_hpc:
|
|
@@ -1274,8 +1463,8 @@ def main():
|
|
| 1274 |
# ββ Compute and report exact per-tensor RMSE ββ
|
| 1275 |
try:
|
| 1276 |
CHUNK_BLK = 100_000 # blocks per chunk to bound memory
|
| 1277 |
-
total_se = 0.0
|
| 1278 |
-
total_n = 0
|
| 1279 |
for ci in range(0, n_blocks, CHUNK_BLK):
|
| 1280 |
ce = min(ci + CHUNK_BLK, n_blocks)
|
| 1281 |
chunk_q = q2k_data[ci*84:ce*84]
|
|
@@ -1283,9 +1472,11 @@ def main():
|
|
| 1283 |
orig_chunk = f32[ci*QK_K:ce*QK_K]
|
| 1284 |
n_valid = min(len(orig_chunk), len(deq_chunk))
|
| 1285 |
diff = orig_chunk[:n_valid] - deq_chunk[:n_valid]
|
| 1286 |
-
total_se += np.sum(diff ** 2)
|
| 1287 |
total_n += n_valid
|
| 1288 |
tensor_rmse = np.sqrt(total_se / max(total_n, 1))
|
|
|
|
|
|
|
| 1289 |
q2k_rmse_sum += tensor_rmse
|
| 1290 |
q2k_tensor_count += 1
|
| 1291 |
print(f"\n [Q2_K] {ti['name'][:55]} RMSE={tensor_rmse:.6e}")
|
|
@@ -1326,7 +1517,13 @@ def main():
|
|
| 1326 |
print(f" β Compression: {compression:>42.1f}x β")
|
| 1327 |
if q2k_tensor_count > 0:
|
| 1328 |
mean_rmse = q2k_rmse_sum / q2k_tensor_count
|
| 1329 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1330 |
print(f" β Total time: {elapsed:>39.1f} sec β")
|
| 1331 |
print(" ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
|
| 1332 |
print()
|
|
@@ -1335,4 +1532,4 @@ def main():
|
|
| 1335 |
|
| 1336 |
|
| 1337 |
if __name__ == '__main__':
|
| 1338 |
-
main()
|
|
|
|
| 10 |
|
| 11 |
Usage:
|
| 12 |
python3 hexstate_requantize.py input.gguf output.gguf
|
| 13 |
+
|
| 14 |
+
ANALOG mode (minimises LAYER OUTPUT error instead of weight RMSE):
|
| 15 |
+
--hessian FILE.hxh full X^T X per tensor (see write_hessian)
|
| 16 |
+
--analog-imatrix diagonal Hessian from --imatrix (weaker, no new
|
| 17 |
+
calibration needed)
|
| 18 |
+
--analog-sweeps N coordinate-descent sweeps (default 8)
|
| 19 |
+
|
| 20 |
+
In ANALOG mode weight RMSE RISES by design. Evaluate with perplexity.
|
| 21 |
"""
|
| 22 |
|
| 23 |
import struct
|
|
|
|
| 61 |
ctypes.c_int, # verbose
|
| 62 |
]
|
| 63 |
|
| 64 |
+
# ANALOG Q2_K (Hessian / output-error objective)
|
| 65 |
+
if hasattr(lib, 'hexstate_quantize_tensor_q2k_analog'):
|
| 66 |
+
lib.hexstate_quantize_tensor_q2k_analog.restype = None
|
| 67 |
+
lib.hexstate_quantize_tensor_q2k_analog.argtypes = [
|
| 68 |
+
ctypes.POINTER(ctypes.c_float), # weights
|
| 69 |
+
ctypes.c_int64, # n_elements
|
| 70 |
+
ctypes.c_int64, # n_in (row length)
|
| 71 |
+
ctypes.POINTER(ctypes.c_float), # H (n_in*n_in) or NULL
|
| 72 |
+
ctypes.c_void_p, # output
|
| 73 |
+
ctypes.POINTER(ctypes.c_float), # out_error
|
| 74 |
+
ctypes.c_int, # n_sweeps
|
| 75 |
+
ctypes.c_int, # verbose
|
| 76 |
+
]
|
| 77 |
+
lib.hexstate_q2k_hessian_bytes.restype = ctypes.c_int64
|
| 78 |
+
lib.hexstate_q2k_hessian_bytes.argtypes = [ctypes.c_int64]
|
| 79 |
+
|
| 80 |
lib.hexstate_q2k_block_bytes.restype = ctypes.c_int
|
| 81 |
lib.hexstate_q2k_block_bytes.argtypes = []
|
| 82 |
lib.hexstate_q2k_block_elements.restype = ctypes.c_int
|
|
|
|
| 148 |
f.read(sz)
|
| 149 |
|
| 150 |
|
| 151 |
+
# βββ Hessian (X^T X) support for the ANALOG objective βββββββββββββββββββββββ
|
| 152 |
+
#
|
| 153 |
+
# FILE FORMAT (.hxh) β little-endian throughout
|
| 154 |
+
#
|
| 155 |
+
# magic 4 bytes b"HXH1"
|
| 156 |
+
# n_entries uint32
|
| 157 |
+
# repeated n_entries times:
|
| 158 |
+
# name_len uint32
|
| 159 |
+
# name name_len bytes, UTF-8 tensor name (GGUF naming)
|
| 160 |
+
# n_in uint32 row length; must be a multiple of 256
|
| 161 |
+
# H n_in*n_in float32, ROW-MAJOR
|
| 162 |
+
#
|
| 163 |
+
# H must be X^T X / n_samples for that layer's INPUT activations, damped on
|
| 164 |
+
# the diagonal (add ~1% of mean(diag) to keep it invertible). This is NOT a
|
| 165 |
+
# llama.cpp imatrix: an imatrix stores only diag(X^T X), the n_in diagonal
|
| 166 |
+
# entries. Entries may be shared between tensors with the same input space
|
| 167 |
+
# (e.g. attn_q / attn_k / attn_v) by writing the same H under each name.
|
| 168 |
+
#
|
| 169 |
+
# Memory: n_in^2 * 4 bytes. 4 MiB at n_in=1024, 64 MiB at n_in=4096.
|
| 170 |
+
|
| 171 |
+
HESSIAN_MAGIC = b"HXH1"
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def read_hessian(path):
|
| 175 |
+
"""Read a .hxh file. Returns dict: tensor_name -> float32 (n_in, n_in)."""
|
| 176 |
+
import struct as st
|
| 177 |
+
out = {}
|
| 178 |
+
with open(path, 'rb') as f:
|
| 179 |
+
if f.read(4) != HESSIAN_MAGIC:
|
| 180 |
+
raise ValueError(f"{path}: not a HXH1 Hessian file")
|
| 181 |
+
n_entries = st.unpack('<I', f.read(4))[0]
|
| 182 |
+
for _ in range(n_entries):
|
| 183 |
+
nl = st.unpack('<I', f.read(4))[0]
|
| 184 |
+
name = f.read(nl).decode('utf-8', errors='replace')
|
| 185 |
+
n_in = st.unpack('<I', f.read(4))[0]
|
| 186 |
+
buf = f.read(n_in * n_in * 4)
|
| 187 |
+
if len(buf) != n_in * n_in * 4:
|
| 188 |
+
raise ValueError(f"{path}: truncated entry for {name}")
|
| 189 |
+
out[name] = np.frombuffer(buf, dtype=np.float32).reshape(n_in, n_in)
|
| 190 |
+
return out
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def write_hessian(path, entries):
|
| 194 |
+
"""entries: dict name -> (n_in, n_in) array convertible to float32."""
|
| 195 |
+
import struct as st
|
| 196 |
+
with open(path, 'wb') as f:
|
| 197 |
+
f.write(HESSIAN_MAGIC)
|
| 198 |
+
f.write(st.pack('<I', len(entries)))
|
| 199 |
+
for name, H in entries.items():
|
| 200 |
+
H = np.ascontiguousarray(H, dtype=np.float32)
|
| 201 |
+
assert H.ndim == 2 and H.shape[0] == H.shape[1], name
|
| 202 |
+
nb = name.encode('utf-8')
|
| 203 |
+
f.write(st.pack('<I', len(nb)))
|
| 204 |
+
f.write(nb)
|
| 205 |
+
f.write(st.pack('<I', H.shape[0]))
|
| 206 |
+
f.write(H.tobytes())
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def hessian_from_imatrix(imat_row, n_in, damp=0.01):
|
| 210 |
+
"""Build a DIAGONAL Hessian from an existing imatrix row.
|
| 211 |
+
|
| 212 |
+
An imatrix gives diag(X^T X) only, so this discards all cross-column
|
| 213 |
+
correlation. It is strictly weaker than a real Hessian -- measured on a
|
| 214 |
+
synthetic layer, diagonal-only recovers roughly half the output-error
|
| 215 |
+
gain that a full H delivers -- but it needs no new calibration run and
|
| 216 |
+
lets the analog path be exercised with data you already have.
|
| 217 |
+
"""
|
| 218 |
+
d = np.asarray(imat_row, dtype=np.float64).ravel()
|
| 219 |
+
if d.size < n_in:
|
| 220 |
+
d = np.tile(d, int(np.ceil(n_in / max(d.size, 1))))
|
| 221 |
+
d = d[:n_in].copy()
|
| 222 |
+
d[~np.isfinite(d)] = 0.0
|
| 223 |
+
if d.max() <= 0:
|
| 224 |
+
d[:] = 1.0
|
| 225 |
+
d += damp * d.mean()
|
| 226 |
+
H = np.zeros((n_in, n_in), dtype=np.float32)
|
| 227 |
+
np.fill_diagonal(H, d.astype(np.float32))
|
| 228 |
+
return H
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def quantize_tensor_q2k_analog(f32_data, n_in, H, sweeps=0, verbose=1):
|
| 232 |
+
"""Assign fresh 2-bit codes minimising LAYER OUTPUT error (not weight RMSE).
|
| 233 |
+
|
| 234 |
+
Weight RMSE is EXPECTED to rise; judge this path by perplexity.
|
| 235 |
+
Returns (bytes, n_blocks). Raises if the C library lacks the entry point.
|
| 236 |
+
"""
|
| 237 |
+
lib = _load_hexstate_lib()
|
| 238 |
+
if lib is None or not hasattr(lib, 'hexstate_quantize_tensor_q2k_analog'):
|
| 239 |
+
raise RuntimeError("libhexstate_q2k.so has no analog entry point; rebuild")
|
| 240 |
+
|
| 241 |
+
n_elements = len(f32_data)
|
| 242 |
+
if n_elements % QK_K != 0:
|
| 243 |
+
pad = QK_K - (n_elements % QK_K)
|
| 244 |
+
f32_data = np.concatenate([f32_data, np.zeros(pad, dtype=np.float32)])
|
| 245 |
+
n_elements = len(f32_data)
|
| 246 |
+
|
| 247 |
+
n_blocks = n_elements // QK_K
|
| 248 |
+
output = np.zeros(n_blocks * lib.hexstate_q2k_block_bytes(), dtype=np.uint8)
|
| 249 |
+
error = ctypes.c_float(0.0)
|
| 250 |
+
|
| 251 |
+
f32c = np.ascontiguousarray(f32_data, dtype=np.float32)
|
| 252 |
+
Hc = np.ascontiguousarray(H, dtype=np.float32)
|
| 253 |
+
lib.hexstate_quantize_tensor_q2k_analog(
|
| 254 |
+
f32c.ctypes.data_as(ctypes.POINTER(ctypes.c_float)),
|
| 255 |
+
ctypes.c_int64(n_elements),
|
| 256 |
+
ctypes.c_int64(int(n_in)),
|
| 257 |
+
Hc.ctypes.data_as(ctypes.POINTER(ctypes.c_float)),
|
| 258 |
+
output.ctypes.data_as(ctypes.c_void_p),
|
| 259 |
+
ctypes.byref(error),
|
| 260 |
+
ctypes.c_int(int(sweeps)),
|
| 261 |
+
ctypes.c_int(int(verbose)),
|
| 262 |
+
)
|
| 263 |
+
return output.tobytes(), n_blocks
|
| 264 |
+
|
| 265 |
+
|
| 266 |
def read_imatrix(path):
|
| 267 |
"""Read llama.cpp importance matrix file (GGUF or legacy .dat format).
|
| 268 |
|
|
|
|
| 873 |
print(f" WARNING: imatrix file not found: {imat_path}")
|
| 874 |
break
|
| 875 |
|
| 876 |
+
# ββ ANALOG objective options ββ
|
| 877 |
+
hessian_data = None
|
| 878 |
+
analog_from_imat = '--analog-imatrix' in sys.argv
|
| 879 |
+
analog_sweeps = 0
|
| 880 |
+
for i, arg in enumerate(sys.argv):
|
| 881 |
+
if arg == '--hessian' and i + 1 < len(sys.argv):
|
| 882 |
+
hpath = sys.argv[i + 1]
|
| 883 |
+
if os.path.exists(hpath):
|
| 884 |
+
hessian_data = read_hessian(hpath)
|
| 885 |
+
print(f" Loaded Hessian: {len(hessian_data)} tensors from {hpath}")
|
| 886 |
+
else:
|
| 887 |
+
print(f" WARNING: Hessian file not found: {hpath}")
|
| 888 |
+
elif arg == '--analog-sweeps' and i + 1 < len(sys.argv):
|
| 889 |
+
analog_sweeps = int(sys.argv[i + 1])
|
| 890 |
+
use_analog = (hessian_data is not None) or analog_from_imat
|
| 891 |
+
if use_analog:
|
| 892 |
+
print(" ANALOG MODE: minimising LAYER OUTPUT error, not weight RMSE.")
|
| 893 |
+
print(" Weight RMSE will RISE. Evaluate with perplexity, not RMSE.")
|
| 894 |
+
if analog_from_imat and hessian_data is None:
|
| 895 |
+
print(" Using DIAGONAL Hessian from imatrix (~half the gain of full H).")
|
| 896 |
+
|
| 897 |
# Check for HPC C library
|
| 898 |
use_hpc = _load_hexstate_lib() is not None
|
| 899 |
|
|
|
|
| 1217 |
total_quant_bytes = 0
|
| 1218 |
total_keep_bytes = 0
|
| 1219 |
total_rmse = 0.0
|
| 1220 |
+
# Element-weighted global accumulators. A plain mean of per-tensor
|
| 1221 |
+
# RMSEs weights a 4K-element norm tensor the same as a 100M-element
|
| 1222 |
+
# FFN, so it is dominated by the small tensors and is the wrong
|
| 1223 |
+
# thing to tune against. Track sum-of-squared-error and element
|
| 1224 |
+
# count instead, and derive the true global RMSE at the end.
|
| 1225 |
+
q2k_se_sum = 0.0 # Ξ£ squared error over all Q2_K elements
|
| 1226 |
+
q2k_elem_count = 0 # Ξ£ elements
|
| 1227 |
+
q2k_rmse_sum = 0.0 # kept for the unweighted mean (reported too)
|
| 1228 |
q2k_tensor_count = 0
|
| 1229 |
|
| 1230 |
for i, ti in enumerate(tensor_infos):
|
|
|
|
| 1395 |
imat_full = np.tile(iw, n_rows)[:ti['n_elements']]
|
| 1396 |
|
| 1397 |
n_el = ti['n_elements']
|
| 1398 |
+
|
| 1399 |
+
# ββ ANALOG path: fresh 2-bit codes vs output error ββ
|
| 1400 |
+
analog_H = None
|
| 1401 |
+
analog_n_in = ti['dims'][0] if ti.get('dims') else 0
|
| 1402 |
+
if use_analog and analog_n_in and analog_n_in % QK_K == 0 \
|
| 1403 |
+
and n_el % analog_n_in == 0:
|
| 1404 |
+
if hessian_data and ti['name'] in hessian_data:
|
| 1405 |
+
Hcand = hessian_data[ti['name']]
|
| 1406 |
+
if Hcand.shape[0] == analog_n_in:
|
| 1407 |
+
analog_H = Hcand
|
| 1408 |
+
if analog_H is None and analog_from_imat and imatrix_data \
|
| 1409 |
+
and ti['name'] in imatrix_data:
|
| 1410 |
+
analog_H = hessian_from_imatrix(
|
| 1411 |
+
imatrix_data[ti['name']], analog_n_in)
|
| 1412 |
+
|
| 1413 |
+
if analog_H is not None:
|
| 1414 |
+
q2k_data, n_blocks = quantize_tensor_q2k_analog(
|
| 1415 |
+
f32, analog_n_in, analog_H, sweeps=analog_sweeps)
|
| 1416 |
+
src = 'full-H' if (hessian_data and ti['name'] in hessian_data) \
|
| 1417 |
+
else 'diag-H'
|
| 1418 |
+
print(f" [analog:{src}] n_in={analog_n_in} "
|
| 1419 |
+
f"rows={n_el // analog_n_in}")
|
| 1420 |
+
elif use_hpc and n_el <= HPC_CHUNK:
|
| 1421 |
# Small tensor β single HPC pass
|
| 1422 |
q2k_data, n_blocks = quantize_tensor_q2k_hpc(f32, opt_mode=2, importance=imat_full)
|
| 1423 |
elif use_hpc:
|
|
|
|
| 1463 |
# ββ Compute and report exact per-tensor RMSE ββ
|
| 1464 |
try:
|
| 1465 |
CHUNK_BLK = 100_000 # blocks per chunk to bound memory
|
| 1466 |
+
total_se = 0.0 # float64: np.sum on float32 would
|
| 1467 |
+
total_n = 0 # round away small terms on big tensors
|
| 1468 |
for ci in range(0, n_blocks, CHUNK_BLK):
|
| 1469 |
ce = min(ci + CHUNK_BLK, n_blocks)
|
| 1470 |
chunk_q = q2k_data[ci*84:ce*84]
|
|
|
|
| 1472 |
orig_chunk = f32[ci*QK_K:ce*QK_K]
|
| 1473 |
n_valid = min(len(orig_chunk), len(deq_chunk))
|
| 1474 |
diff = orig_chunk[:n_valid] - deq_chunk[:n_valid]
|
| 1475 |
+
total_se += float(np.sum(diff.astype(np.float64) ** 2))
|
| 1476 |
total_n += n_valid
|
| 1477 |
tensor_rmse = np.sqrt(total_se / max(total_n, 1))
|
| 1478 |
+
q2k_se_sum += total_se
|
| 1479 |
+
q2k_elem_count += total_n
|
| 1480 |
q2k_rmse_sum += tensor_rmse
|
| 1481 |
q2k_tensor_count += 1
|
| 1482 |
print(f"\n [Q2_K] {ti['name'][:55]} RMSE={tensor_rmse:.6e}")
|
|
|
|
| 1517 |
print(f" β Compression: {compression:>42.1f}x β")
|
| 1518 |
if q2k_tensor_count > 0:
|
| 1519 |
mean_rmse = q2k_rmse_sum / q2k_tensor_count
|
| 1520 |
+
# Global RMSE = sqrt(Ξ£ SE / Ξ£ N): every quantized weight counts once,
|
| 1521 |
+
# regardless of which tensor it lives in. This is the number to tune
|
| 1522 |
+
# against; the unweighted per-tensor mean is kept below for continuity
|
| 1523 |
+
# with previous runs but is dominated by small tensors.
|
| 1524 |
+
global_rmse = np.sqrt(q2k_se_sum / max(q2k_elem_count, 1))
|
| 1525 |
+
print(f" β Global Q2_K RMSE (element-wtd): {global_rmse:>12.6e} β")
|
| 1526 |
+
print(f" β Mean Q2_K RMSE (per-tensor, unwtd): {mean_rmse:>12.6e} β")
|
| 1527 |
print(f" β Total time: {elapsed:>39.1f} sec β")
|
| 1528 |
print(" ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
|
| 1529 |
print()
|
|
|
|
| 1532 |
|
| 1533 |
|
| 1534 |
if __name__ == '__main__':
|
| 1535 |
+
main()
|