| |
| """ |
| encode_tr3_v31.py — GLM-5.2 NVFP4 -> EXL3-trellis-3.0 hybrid production encoder. |
| v2: CALIBRATED LDLQ (owner mandate — the v1 identity-Hessian shortcut is gone). |
| v3: CROSS-SLICE LOCKSTEP LDLQ — same math, same bits, ~2-3x the speed. |
| v3.1: v3 + CROSS-SLICE LOCKSTEP g_scale GOLDEN-SECTION SEARCH — same bits. |
| |
| v2's LDLQ main pass launches ext.quantize_tiles on one 16-row block of ONE |
| slice at a time (n=512 slices -> 32 tiles/call) against a kernel wave of |
| 2*SM tile-slots (296 on B200), idling ~89% of the wave. v3 co-processes |
| many independent slice-walks in LOCKSTEP: at each LDLQ step it gathers the |
| current 16-row block from every active walk into ONE quantize_tiles call, |
| scatters the results back, and runs each walk's error-feedback GEMMs on |
| that walk's own tensors. Per-slice operand values and op order are exactly |
| v2's, and each tile's trellis DP is independent of every other tile in the |
| batch (quantize.cu: tile_idx = blockIdx.x; all pointers offset purely by |
| tile_idx; per-tile scratch slots), so v3 output is BIT-IDENTICAL to v2 — |
| asserted once per worker (lockstep_self_check) and proven on real slices by |
| --oracle (hard deployment gate). |
| |
| New CLI (encode CLI otherwise unchanged): --lockstep N (default 'auto' = |
| 12 = all 3*TP slice-walks of one expert; N>12 pools ceil(N/12) experts). |
| Validation extras: --oracle / --oracle-experts / --oracle-log, --bench / |
| --bench-experts (both read-only wrt --work). Everything else — prologue |
| math (finalize_capture_H, regularize, g_scale_gss per slice, seeds, su/sv |
| draws), resumability, bitmap selection, bit-exactness asserts, logging, |
| assemble/upload — is v2 verbatim. Done-JSON gains a "lockstep" field. |
| |
| v3.1 extends the same lockstep idea to the remaining serial hot spot, |
| regularize()'s per-slice g_scale golden-section search: the 12 slice-walks' |
| searches are independent, so at each golden-section step ALL active |
| searches' (sampled tiles x candidate scale) evaluations are gathered into |
| ONE quantize_tiles call, the per-search MSEs scattered back, and each |
| search's bracket advanced independently (searches whose bracket closes drop |
| out of the pool; survivors keep pooling). Tile sampling, candidate scales, |
| iteration sequence, bracket arithmetic and tie behavior are VERBATIM |
| v3 (= v2 = reference), so output stays bit-identical — asserted once per |
| worker (pooled-vs-sequential g_scale equality on the first expert pool, |
| g_scale_gss_lockstep self_check) and proven on real slices by --oracle |
| (v3.1 vs v3 vs v2 byte equality, hard deployment gate). CLI unchanged; |
| done-JSON additionally gains "gss_lockstep": true. |
| |
| Builds the KLC hybrid checkpoint from lukealonso/GLM-5.2-NVFP4 (ModelOpt-style |
| NVFP4, 87 shards): |
| |
| * per MoE layer (3..77): encode ALL 256 routed experts with EXL3 trellis at |
| exactly 3.0 bpw via the exllamav3 v0.0.43 CALIBRATED path (finalize_capture_H |
| -> block LDL -> ldlq blocked quantization with error feedback), TP4 per-slice |
| (gate/up N-sliced 4x[512,6144], down K-sliced 4x[6144,512], each slice its |
| own Hadamard/su/sv/g_scale/trellis encode); |
| * Hessians come from the OWNER'S calibration corpus via capture_hessians.py |
| (Pass A) — stored MoE-input activations x + top-8 routing ids per layer: |
| - gate/up slice (k=6144): H_e = X_e^T X_e over the tokens ROUTED to |
| expert e. N-slicing does not change the input side, so all 8 gate/up |
| slices of an expert share ONE 6144x6144 H (and, per reference |
| semantics, one su drawn at first finalize; sv per slice). |
| - down slice (k=512): I_e = silu(X_e Wg^T) * (X_e Wu^T) computed offline |
| from the stored routed x with the DEQUANTIZED gate/up weights |
| (GLM-5.2 config: hidden_act=silu, no swiglu clamp), H_down_e = I_e^T I_e |
| [2048x2048]; K-slice r uses the [512r,512r+512) DIAGONAL block — |
| slice-local LDLQ, consistent with slice-before-encode (each rank's |
| down slice is an independent linear with input I_e[:,512r:512r+512), |
| so its H is exactly that diagonal block; cross-slice H terms have no |
| consumer because slices are encoded and Hadamard-transformed |
| independently). |
| - cold experts: if an expert saw < --min-routed (1024) routed tokens, |
| its gate/up H falls back to the LAYER-level H (all tokens) and its |
| down H to I over a seeded subsample of all tokens through that |
| expert's own gate/up — recorded in the done-JSON, never a failure. |
| * keep the 64 experts with the HIGHEST trellis round-trip error as NVFP4 |
| (copied byte-exact from the source; their trellis encodes are discarded); |
| RT-error is now measured under the calibrated encode; |
| * carry every non-(routed-expert) tensor byte-exact (verified by sha256); |
| * assemble a complete checkpoint dir + index + tier_bitmap + MANIFEST; |
| * upload to a private HF repo (token from HF_TOKEN env, never logged). |
| |
| BIT-EXACTNESS GUARANTEES (owner mandate — these are correctness checks, not |
| quality gates; there is NO quality evaluation anywhere in this driver): |
| (a) every carried tensor: sha256(source payload bytes) is asserted equal to |
| sha256(bytes re-read from the written output shard); |
| (b) every trellis tensor: pack->unpack index equality (torch.equal) AND |
| ext.reconstruct(packed) is asserted bit-equal to the encoder's own |
| reconstructed values (the values the home exl3 kernel will decode); |
| (c) --assemble writes MANIFEST.sha256 over every output file and audits the |
| index (every weight_map entry -> existing shard containing that tensor, |
| and every shard tensor -> weight_map). |
| |
| Per-expert RT-error is computed ONLY to choose the 64 NVFP4 keeps per layer. |
| It never gates, never aborts. |
| |
| CALIBRATION IS MANDATORY: --encode refuses to start unless the capture dir |
| (Pass A, capture_hessians.py) is complete for every requested layer. There is |
| no identity-Hessian escape hatch. The reference q_fallback branch (count==0 / |
| degenerate diagonal) is vendored for faithfulness but cannot trigger under the |
| >= min-routed floor; if it ever does, it is recorded loudly in the done-JSON. |
| |
| DEPENDENCIES on the box (see RUNBOOK_TR3.md): |
| torch==2.11.0+cu130, numpy, safetensors (unused at runtime but harmless), |
| huggingface_hub, and the exllamav3 v0.0.43 cu132/torch2.11/cp312 wheel |
| installed with --no-deps. Only the compiled extension `exllamav3_ext` is |
| imported; the pure-Python quantization orchestration below is vendored |
| VERBATIM from exllamav3 v0.0.43 (MIT, (c) turboderp), file |
| exllamav3/modules/quant/exl3_lib/quantize.py, so the heavy deps of the |
| exllamav3 python package (flash_attn, xformers, formatron, fla) are never |
| imported. |
| |
| OUTPUT EXL3 TENSOR SCHEMA (native exllamav3 Linear storage; loadable by |
| exllamav3.modules.quant.exl3.LinearEXL3 unmodified): |
| model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}.trellis int16 [K/16, N/16, 48] |
| model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}.suh float16 [K] |
| model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}.svh float16 [N] |
| model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}.mcg int32 scalar (0xCBAC1FED) |
| where for proj in {gate_proj, up_proj}: K=6144 (model hidden), N=512 |
| (=2048/4, rank r holds output rows [512r, 512r+512) of the full [2048,6144] |
| weight); for down_proj: K=512 (rank r holds input cols [512r, 512r+512) of |
| the full [6144,2048] weight), N=6144. K/N are exl3 conventions |
| (in_features/out_features); trellis last dim = 16*bits = 48 at 3.0 bpw. |
| |
| Usage (all commands also in RUNBOOK_TR3.md; capture_hessians.py --capture must |
| have completed first): |
| python3 encode_tr3.py --smoke # kernel + calibrated-path check (synthetic H) |
| python3 encode_tr3.py --encode [--layers 3-77] # multi-GPU calibrated encode (resumable) |
| python3 encode_tr3.py --assemble # build final checkpoint dir |
| python3 encode_tr3.py --upload [--repo NAME] # HF upload (HF_TOKEN env) |
| """ |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import hashlib |
| import json |
| import math |
| import os |
| import struct |
| import subprocess |
| import sys |
| import time |
| import traceback |
| from functools import lru_cache |
|
|
| |
| |
| |
|
|
| DEF_SRC = "/root/models/luke-nvfp4" |
| DEF_WORK = "/root/tr3_work" |
| DEF_OUT = "/root/out/GLM-5.2-NVFP4-TR3-Hybrid" |
| DEF_REPO = "brandonmusic/GLM-5.2-NVFP4-TR3-Hybrid" |
| DEF_CAPTURE = "/root/tr3_capture" |
|
|
| BITS = 3 |
| KEEP_NVFP4 = 64 |
| TP = 4 |
| SEED_BASE = 20260711 |
| SIGMA_REG = 0.025 |
| MIN_ROUTED = 1024 |
| FALLBACK_ROWS = 131072 |
| HCHUNK = 65536 |
|
|
| FIRST_MOE_LAYER = 3 |
| NUM_LAYERS = 78 |
| NUM_EXPERTS = 256 |
| HIDDEN = 6144 |
| MOE_INTER = 2048 |
| SLICE = MOE_INTER // TP |
|
|
| PROJS = ("gate_proj", "up_proj", "down_proj") |
|
|
| |
| HAD_K, HAD_N = 128, 128 |
| CODEBOOK_SCALE = 1.24371088 |
| MCG_MULT = 0xCBAC1FED |
|
|
| ST_DTYPE_SIZE = { |
| "BOOL": 1, "U8": 1, "I8": 1, "F8_E4M3": 1, "F8_E5M2": 1, |
| "I16": 2, "U16": 2, "F16": 2, "BF16": 2, |
| "I32": 4, "U32": 4, "F32": 4, |
| "I64": 8, "U64": 8, "F64": 8, |
| } |
|
|
| CHUNK = 64 << 20 |
|
|
|
|
| def log(msg: str, logfile: str | None = None): |
| line = f"{time.strftime('%Y-%m-%d %H:%M:%S')} | {msg}" |
| print(line, flush=True) |
| if logfile: |
| with open(logfile, "a") as f: |
| f.write(line + "\n") |
|
|
|
|
| |
| |
| |
|
|
| class STReader: |
| """Minimal safetensors reader working on raw byte ranges.""" |
|
|
| def __init__(self, path: str): |
| self.path = path |
| with open(path, "rb") as f: |
| hlen = struct.unpack("<Q", f.read(8))[0] |
| header = json.loads(f.read(hlen)) |
| self.data_start = 8 + hlen |
| self.tensors = {} |
| for name, info in header.items(): |
| if name == "__metadata__": |
| continue |
| s, e = info["data_offsets"] |
| self.tensors[name] = (info["dtype"], tuple(info["shape"]), |
| self.data_start + s, self.data_start + e) |
|
|
| def nbytes(self, name: str) -> int: |
| _, _, s, e = self.tensors[name] |
| return e - s |
|
|
| def read_bytes(self, name: str) -> bytes: |
| _, _, s, e = self.tensors[name] |
| with open(self.path, "rb") as f: |
| f.seek(s) |
| return f.read(e - s) |
|
|
| def sha256_stream(self, name: str) -> str: |
| _, _, s, e = self.tensors[name] |
| h = hashlib.sha256() |
| with open(self.path, "rb") as f: |
| f.seek(s) |
| left = e - s |
| while left: |
| b = f.read(min(CHUNK, left)) |
| if not b: |
| raise IOError(f"short read on {self.path}:{name}") |
| h.update(b) |
| left -= len(b) |
| return h.hexdigest() |
|
|
|
|
| def st_file_complete(path: str) -> bool: |
| """A shard is complete iff its header parses and the file covers all data. |
| (hf downloads rename atomically, so existence normally suffices; this |
| also guards against partial copies.)""" |
| try: |
| size = os.path.getsize(path) |
| if size < 16: |
| return False |
| with open(path, "rb") as f: |
| hlen = struct.unpack("<Q", f.read(8))[0] |
| if hlen > 100 << 20: |
| return False |
| header = json.loads(f.read(hlen)) |
| end = max((v["data_offsets"][1] for k, v in header.items() |
| if k != "__metadata__"), default=0) |
| return size >= 8 + hlen + end |
| except Exception: |
| return False |
|
|
|
|
| def wait_for_shard(path: str, logfile: str | None = None): |
| waited = False |
| while not (os.path.exists(path) and st_file_complete(path)): |
| if not waited: |
| log(f"waiting for shard {os.path.basename(path)} (download in progress?)", logfile) |
| waited = True |
| time.sleep(30) |
| if waited: |
| log(f"shard ready: {os.path.basename(path)}", logfile) |
|
|
|
|
| def write_safetensors(path: str, entries: list, metadata: dict | None = None): |
| """entries: list of (name, dtype_str, shape:tuple, payload) where payload is |
| bytes or a zero-arg callable returning bytes. Streams to disk; returns |
| (per_tensor_payload_sha256: dict, file_sha256: str).""" |
| header = {} |
| if metadata: |
| header["__metadata__"] = metadata |
| off = 0 |
| sizes = [] |
| for name, dt, shape, _ in entries: |
| n = ST_DTYPE_SIZE[dt] |
| for d in shape: |
| n *= d |
| header[name] = {"dtype": dt, "shape": list(shape), "data_offsets": [off, off + n]} |
| sizes.append(n) |
| off += n |
| assert len(header) == len(entries) + (1 if metadata else 0), "duplicate tensor name in shard" |
| hjson = json.dumps(header, separators=(",", ":")).encode() |
| pad = (8 - (len(hjson) % 8)) % 8 |
| hjson += b" " * pad |
|
|
| tensor_sha = {} |
| fh = hashlib.sha256() |
| tmp = path + ".tmp" |
| with open(tmp, "wb") as f: |
| head = struct.pack("<Q", len(hjson)) + hjson |
| f.write(head) |
| fh.update(head) |
| for (name, dt, shape, payload), n in zip(entries, sizes): |
| b = payload() if callable(payload) else payload |
| if len(b) != n: |
| raise ValueError(f"{name}: payload {len(b)} bytes != header {n}") |
| f.write(b) |
| fh.update(b) |
| tensor_sha[name] = hashlib.sha256(b).hexdigest() |
| os.replace(tmp, path) |
| return tensor_sha, fh.hexdigest() |
|
|
|
|
| def sha256_file(path: str) -> str: |
| h = hashlib.sha256() |
| with open(path, "rb") as f: |
| while True: |
| b = f.read(CHUNK) |
| if not b: |
| break |
| h.update(b) |
| return h.hexdigest() |
|
|
|
|
| def sha256_range(path: str, start: int, end: int) -> str: |
| h = hashlib.sha256() |
| with open(path, "rb") as f: |
| f.seek(start) |
| left = end - start |
| while left: |
| b = f.read(min(CHUNK, left)) |
| if not b: |
| raise IOError(f"short read {path} [{start},{end})") |
| h.update(b) |
| left -= len(b) |
| return h.hexdigest() |
|
|
|
|
| |
| |
| |
|
|
| class SourceModel: |
| def __init__(self, src: str): |
| self.src = src |
| with open(os.path.join(src, "config.json")) as f: |
| self.config = json.load(f) |
| c = self.config |
| assert c["num_hidden_layers"] == NUM_LAYERS, c["num_hidden_layers"] |
| assert c["first_k_dense_replace"] == FIRST_MOE_LAYER |
| assert c["n_routed_experts"] == NUM_EXPERTS |
| assert c["hidden_size"] == HIDDEN |
| assert c["moe_intermediate_size"] == MOE_INTER |
| with open(os.path.join(src, "model.safetensors.index.json")) as f: |
| self.index = json.load(f) |
| self.weight_map = self.index["weight_map"] |
| self._readers = {} |
|
|
| def shard_path(self, tensor_name: str) -> str: |
| return os.path.join(self.src, self.weight_map[tensor_name]) |
|
|
| def reader_for(self, tensor_name: str, logfile=None) -> STReader: |
| p = self.shard_path(tensor_name) |
| if p not in self._readers: |
| wait_for_shard(p, logfile) |
| self._readers[p] = STReader(p) |
| return self._readers[p] |
|
|
| def moe_layers(self): |
| return list(range(FIRST_MOE_LAYER, NUM_LAYERS)) |
|
|
|
|
| def expert_key(L, E, proj, suffix): |
| return f"model.layers.{L}.mlp.experts.{E}.{proj}.{suffix}" |
|
|
|
|
| |
| |
| |
| |
| |
|
|
| def _lazy_torch(): |
| import torch |
| import exllamav3_ext as ext |
| return torch, ext |
|
|
|
|
| @lru_cache |
| def tensor_core_perm(device): |
| torch, _ = _lazy_torch() |
| perm_a = [0] * 256 |
| for t in range(32): |
| r0 = (t % 4) * 2 |
| r1 = r0 + 1 |
| r2 = r0 + 8 |
| r3 = r0 + 9 |
| c0 = t // 4 |
| c1 = c0 + 8 |
| perm_a[t * 8 + 0] = r0 * 16 + c0 |
| perm_a[t * 8 + 1] = r1 * 16 + c0 |
| perm_a[t * 8 + 2] = r2 * 16 + c0 |
| perm_a[t * 8 + 3] = r3 * 16 + c0 |
| perm_a[t * 8 + 4] = r0 * 16 + c1 |
| perm_a[t * 8 + 5] = r1 * 16 + c1 |
| perm_a[t * 8 + 6] = r2 * 16 + c1 |
| perm_a[t * 8 + 7] = r3 * 16 + c1 |
| return torch.tensor(perm_a, dtype=torch.int, device=device) |
|
|
|
|
| @lru_cache |
| def tensor_core_perm_i(device): |
| torch, _ = _lazy_torch() |
| return torch.argsort(tensor_core_perm(device)) |
|
|
|
|
| @lru_cache |
| def _hadamard_f16(n: int): |
| """Sylvester construction, identical to exllamav3 util/hadamard.py for |
| power-of-two sizes (base case = hadamard_1.txt = [[1]], built in fp16).""" |
| torch, _ = _lazy_torch() |
| assert n & (n - 1) == 0 and n >= 1 |
| h = torch.ones((1, 1), dtype=torch.float16) |
| while h.shape[0] < n: |
| d = h.shape[0] |
| s = torch.empty((d * 2, d * 2), dtype=h.dtype) |
| s[:d, :d] = h |
| s[:d, d:] = h |
| s[d:, :d] = h |
| s[d:, d:] = -h |
| h = s |
| return h |
|
|
|
|
| @lru_cache |
| def get_hadamard_dt(n, device, dtype, scale=1.0): |
| had = _hadamard_f16(n).to(device=device, dtype=dtype, copy=True) |
| had *= scale |
| return had |
|
|
|
|
| def preapply_had_l(x, had_dim): |
| torch, _ = _lazy_torch() |
| k, n = x.shape |
| x_dtype = x.dtype |
| x = x.to(torch.float) |
| had = get_hadamard_dt(had_dim, x.device, x.dtype, 1 / math.sqrt(had_dim)) |
| x = (had @ x.view(-1, had_dim, n)).view(k, n) |
| return x.to(x_dtype) |
|
|
|
|
| def preapply_had_r(x, had_dim): |
| torch, _ = _lazy_torch() |
| k, n = x.shape |
| x_dtype = x.dtype |
| x = x.to(torch.float) |
| had = get_hadamard_dt(had_dim, x.device, x.dtype, 1 / math.sqrt(had_dim)) |
| x = (x.view(k, -1, had_dim) @ had).view(k, n) |
| return x.to(x_dtype) |
|
|
|
|
| def blockwise_preapply_had_l_(x, had_dim): |
| torch, _ = _lazy_torch() |
| k, n = x.shape |
| assert k % had_dim == 0 and x.dtype == torch.float |
| had = get_hadamard_dt(had_dim, x.device, x.dtype, 1 / math.sqrt(had_dim)) |
| for i in range(k // had_dim): |
| s = i * had_dim |
| x[s:s + had_dim, :] = had @ x[s:s + had_dim, :].view(had_dim, n) |
|
|
|
|
| def blockwise_preapply_had_r_(x, had_dim): |
| torch, _ = _lazy_torch() |
| k, n = x.shape |
| assert n % had_dim == 0 and x.dtype == torch.float |
| had = get_hadamard_dt(had_dim, x.device, x.dtype, 1 / math.sqrt(had_dim)) |
| for i in range(n // had_dim): |
| s = i * had_dim |
| x[:, s:s + had_dim] = x[:, s:s + had_dim] @ had |
|
|
|
|
| def block_rms(x, dim, keepdim=False, blocksize=32): |
| torch, _ = _lazy_torch() |
| n = x.size(dim) |
| sq = None |
| for block in torch.split(x, blocksize, dim=dim): |
| bsq = block.square().sum(dim=dim, keepdim=keepdim) |
| sq = bsq if sq is None else sq + bsq |
| return (sq / n).sqrt() |
|
|
|
|
| @lru_cache |
| def _quant_temp_buffers(K: int): |
| """Same layout as exl3_lib get_temp_buffers, but sized 2*SM-count so the |
| kernel's internal wave (MIN(temp.size(0), 2*num_sms)) is fully utilized.""" |
| torch, _ = _lazy_torch() |
| sms = torch.cuda.get_device_properties(0).multi_processor_count |
| b = 2 * sms |
| temp_costs = torch.zeros((b, 2, 65536 >> K), dtype=torch.half, device="cuda:0") |
| temp_edges = torch.zeros((b, 256, 65536 >> K), dtype=torch.short, device="cuda:0") |
| return temp_costs, temp_edges |
|
|
|
|
| def quantize_tiles_batched(tiles, quant_args): |
| """ext.quantize_tiles over an arbitrary batch of 256-element tiles. |
| The kernel loops internally in waves, so one call suffices.""" |
| torch, ext = _lazy_torch() |
| tiles = tiles.contiguous() |
| assert tiles.shape[1] == 256 and tiles.dtype == torch.float |
| K = quant_args["K"] |
| q_tiles = torch.zeros_like(tiles) |
| q_idx = torch.zeros_like(tiles, dtype=torch.short) |
| temp_costs, temp_edges = _quant_temp_buffers(K) |
| ext.quantize_tiles(tiles, q_tiles, q_idx, temp_costs, temp_edges, |
| K, "mcg" in quant_args, "mul1" in quant_args) |
| return q_tiles, q_idx |
|
|
|
|
| def g_scale_gss(weight_r, quant_args, width=3): |
| """Verbatim golden-section global-scale search (quantize.py g_scale_gss), |
| minus streams/ProgressBar; identical sampling and iteration math.""" |
| torch, _ = _lazy_torch() |
| tiles = [] |
| tiles_k = weight_r.shape[0] // 16 |
| tiles_n = weight_r.shape[1] // 16 |
| perm = tensor_core_perm(weight_r.device) |
| for i in range(max(tiles_k, tiles_n)): |
| for w in range(width): |
| k = (i % tiles_k) * 16 |
| n = ((i + w) % tiles_n) * 16 |
| tile = weight_r[k:k + 16, n:n + 16].clone().view(256) |
| tiles.append(tile[perm]) |
| tiles = torch.stack(tiles) |
|
|
| def test_scale(scale): |
| quant_w, _ = quantize_tiles_batched(tiles * scale, quant_args) |
| return ((quant_w / scale - tiles) ** 2).mean() |
|
|
| phi = (1 + math.sqrt(5)) / 2 |
| resphi = 2 - phi |
| a, b = 0.1, 1.9 |
| tol = 0.01 |
| x1 = a + resphi * (b - a) |
| x2 = b - resphi * (b - a) |
| f1 = test_scale(x1) |
| f2 = test_scale(x2) |
| while abs(b - a) > tol: |
| if f1 < f2: |
| b, x2, f2 = x2, x1, f1 |
| x1 = a + resphi * (b - a) |
| f1 = test_scale(x1) |
| else: |
| a, x1, f1 = x1, x2, f2 |
| x2 = b - resphi * (b - a) |
| f2 = test_scale(x2) |
| return (a + b) / 2, (f1 + f2) / 2 |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| def _gss_bracket_gen(): |
| """Verbatim g_scale_gss() bracket walk as a coroutine: yields candidate |
| scales in the reference evaluation order, receives each candidate's MSE, |
| and returns ((a+b)/2, (f1+f2)/2) exactly like the reference.""" |
| phi = (1 + math.sqrt(5)) / 2 |
| resphi = 2 - phi |
| a, b = 0.1, 1.9 |
| tol = 0.01 |
| x1 = a + resphi * (b - a) |
| x2 = b - resphi * (b - a) |
| f1 = yield x1 |
| f2 = yield x2 |
| while abs(b - a) > tol: |
| if f1 < f2: |
| b, x2, f2 = x2, x1, f1 |
| x1 = a + resphi * (b - a) |
| f1 = yield x1 |
| else: |
| a, x1, f1 = x1, x2, f2 |
| x2 = b - resphi * (b - a) |
| f2 = yield x2 |
| return (a + b) / 2, (f1 + f2) / 2 |
|
|
|
|
| _self_checked_gss = False |
|
|
|
|
| def g_scale_gss_lockstep(pre_ctxs, logfile=None, self_check=False, width=3): |
| """Pooled golden-section g_scale search over many slices' regularized |
| weights (see block comment above). Sets ctx["g_scale"] on every entry, |
| bit-identical to sequential g_scale_gss(ctx["weight_r"], ...). One-time |
| self_check (first pool of each worker): re-runs the UNTOUCHED v3 |
| sequential g_scale_gss per slice and asserts exact g_scale equality |
| before any result is used.""" |
| global _self_checked_gss |
| torch, _ = _lazy_torch() |
| if not pre_ctxs: |
| return |
| qa = pre_ctxs[0]["quant_args"] |
| for c in pre_ctxs: |
| cq = c["quant_args"] |
| assert cq["K"] == qa["K"] and ("mcg" in cq) == ("mcg" in qa) \ |
| and ("mul1" in cq) == ("mul1" in qa), \ |
| "gss lockstep pool requires uniform quantizer args" |
| searches = [] |
| for c in pre_ctxs: |
| weight_r = c["weight_r"] |
| |
| tiles = [] |
| tiles_k = weight_r.shape[0] // 16 |
| tiles_n = weight_r.shape[1] // 16 |
| perm = tensor_core_perm(weight_r.device) |
| for i in range(max(tiles_k, tiles_n)): |
| for w in range(width): |
| k = (i % tiles_k) * 16 |
| n = ((i + w) % tiles_n) * 16 |
| tile = weight_r[k:k + 16, n:n + 16].clone().view(256) |
| tiles.append(tile[perm]) |
| tiles = torch.stack(tiles) |
| gen = _gss_bracket_gen() |
| searches.append({"ctx": c, "tiles": tiles, "gen": gen, |
| "scale": gen.send(None)}) |
| active = list(searches) |
| while active: |
| |
| |
| parts = [s["tiles"] * s["scale"] for s in active] |
| batch = torch.cat(parts, dim=0) if len(parts) > 1 else parts[0] |
| q_w, _ = quantize_tiles_batched(batch, qa) |
| off = 0 |
| mses = [] |
| for s, p in zip(active, parts): |
| m = p.shape[0] |
| |
| mses.append(((q_w[off:off + m] / s["scale"] - s["tiles"]) ** 2).mean()) |
| off += m |
| assert off == batch.shape[0] |
| vals = torch.stack(mses).cpu().tolist() |
| nxt = [] |
| for s, v in zip(active, vals): |
| try: |
| s["scale"] = s["gen"].send(v) |
| nxt.append(s) |
| except StopIteration as e: |
| s["ctx"]["g_scale"] = e.value[0] |
| active = nxt |
| if self_check and not _self_checked_gss: |
| for s in searches: |
| g_seq, _ = g_scale_gss(s["ctx"]["weight_r"], s["ctx"]["quant_args"]) |
| assert g_seq == s["ctx"]["g_scale"], \ |
| f"pooled GSS g_scale {s['ctx']['g_scale']!r} != sequential {g_seq!r}" |
| _self_checked_gss = True |
| log(f"self-check PASSED: pooled GSS ({len(searches)} searches) == sequential " |
| f"g_scale_gss, exact g_scale equality per slice", logfile) |
| for s in searches: |
| s["tiles"] = None |
| s["gen"] = None |
|
|
|
|
| def regularize(weight, su, sv, quant_args, H_diag=None, q_fallback=False): |
| """Verbatim quantize.py regularize() (v0.0.43, full calibrated version: |
| H_diag skew decides out-channel scaling), ProgressBar/verbose/save-image |
| scaffolding removed. Mutates/returns weight.""" |
| torch, _ = _lazy_torch() |
| force_out_scales = quant_args["apply_out_scales"] |
|
|
| |
| |
| |
| if not q_fallback and H_diag is not None: |
| diag = H_diag.sqrt() |
| diag, _ = torch.sort(diag, descending=True) |
| cutoff = diag.shape[0] // 50 |
| skew_factor = diag[:cutoff].sum() / diag.sum() |
| if force_out_scales is None: |
| apply_out_scales = skew_factor.item() < 0.15 |
| else: |
| apply_out_scales = force_out_scales |
| else: |
| apply_out_scales = True if force_out_scales is None else force_out_scales |
|
|
| if q_fallback: |
| apply_out_scales = force_out_scales |
|
|
| out_channel_scales = block_rms(weight, dim=0, keepdim=True) |
| mean = out_channel_scales.mean().item() |
| if mean > 1e-30: |
| out_channel_scales /= mean |
| quant_args["zeros"] = False |
| else: |
| quant_args["zeros"] = True |
| if force_out_scales is not None: |
| apply_out_scales = True |
| zero_out_scales = out_channel_scales.abs() < 1e-30 |
|
|
| if apply_out_scales: |
| out_channel_scales[zero_out_scales] = 0.1 |
| sv = (sv * out_channel_scales + 1e-10).float() |
|
|
| weight /= sv |
| sv[zero_out_scales] = 0.0 |
| blockwise_preapply_had_r_(weight, HAD_N) |
|
|
| in_channel_scales = block_rms(weight, dim=1, keepdim=True) |
| in_channel_scales[in_channel_scales.abs() < 1e-30] = 0.1 |
| su = (su * in_channel_scales / (-CODEBOOK_SCALE) + 1e-10).float() |
| weight /= su |
| blockwise_preapply_had_l_(weight, HAD_K) |
|
|
| g_scale, _ = g_scale_gss(weight, quant_args) |
| weight *= g_scale |
| su /= g_scale |
| return apply_out_scales, weight, g_scale, su, sv |
|
|
|
|
| def regularize_pre(weight, su, sv, quant_args, H_diag=None, q_fallback=False): |
| """v3.1: VERBATIM regularize() head — everything up to (excluding) the |
| g_scale_gss call, so the search itself can run pooled across slices |
| (g_scale_gss_lockstep) followed by regularize_post(). regularize() above |
| stays byte-untouched (v2 verbatim; used by encode_slice, i.e. --smoke and |
| the --oracle reference passes, and by the v3-path encode_slice_prologue).""" |
| torch, _ = _lazy_torch() |
| force_out_scales = quant_args["apply_out_scales"] |
|
|
| |
| |
| |
| if not q_fallback and H_diag is not None: |
| diag = H_diag.sqrt() |
| diag, _ = torch.sort(diag, descending=True) |
| cutoff = diag.shape[0] // 50 |
| skew_factor = diag[:cutoff].sum() / diag.sum() |
| if force_out_scales is None: |
| apply_out_scales = skew_factor.item() < 0.15 |
| else: |
| apply_out_scales = force_out_scales |
| else: |
| apply_out_scales = True if force_out_scales is None else force_out_scales |
|
|
| if q_fallback: |
| apply_out_scales = force_out_scales |
|
|
| out_channel_scales = block_rms(weight, dim=0, keepdim=True) |
| mean = out_channel_scales.mean().item() |
| if mean > 1e-30: |
| out_channel_scales /= mean |
| quant_args["zeros"] = False |
| else: |
| quant_args["zeros"] = True |
| if force_out_scales is not None: |
| apply_out_scales = True |
| zero_out_scales = out_channel_scales.abs() < 1e-30 |
|
|
| if apply_out_scales: |
| out_channel_scales[zero_out_scales] = 0.1 |
| sv = (sv * out_channel_scales + 1e-10).float() |
|
|
| weight /= sv |
| sv[zero_out_scales] = 0.0 |
| blockwise_preapply_had_r_(weight, HAD_N) |
|
|
| in_channel_scales = block_rms(weight, dim=1, keepdim=True) |
| in_channel_scales[in_channel_scales.abs() < 1e-30] = 0.1 |
| su = (su * in_channel_scales / (-CODEBOOK_SCALE) + 1e-10).float() |
| weight /= su |
| blockwise_preapply_had_l_(weight, HAD_K) |
|
|
| return apply_out_scales, weight, su, sv |
|
|
|
|
| def regularize_post(weight, su, g_scale): |
| """v3.1: VERBATIM regularize() tail (g_scale application).""" |
| weight *= g_scale |
| su /= g_scale |
| return weight, su |
|
|
|
|
| @lru_cache |
| def get_quant_stream(device): |
| torch, _ = _lazy_torch() |
| return torch.cuda.Stream(device=device) |
|
|
|
|
| def block_ldl(H, b, quant_args, verbose=False): |
| """Verbatim quantize.py block_ldl() (v0.0.43): Cholesky with diagonal-damping |
| retries, blocked column normalization, identity diagonal blocks. Returns |
| (L, H_cpu); H's GPU storage is reused for L (reference memory trick).""" |
| torch, _ = _lazy_torch() |
| n, _ = H.shape |
| assert (n % b == 0) |
| m = n // b |
|
|
| num_cholesky_retries = 0 |
| retry_cpu = False |
| while True: |
| try: |
| L = torch.linalg.cholesky(H) |
| H_cpu = H.cpu() |
| H.copy_(L) |
| L = H |
| H = H_cpu |
| break |
| except torch._C._LinAlgError as e: |
| num_cholesky_retries += 1 |
| if num_cholesky_retries > 10: |
| print(" ## Cholesky decomp. failed, number of retries exceeded") |
| raise e |
| print(f" !! Cholesky decomp. failed, increasing diagonal damping, " |
| f"attempt {num_cholesky_retries}/10") |
| H.diagonal().add_(2.0 * quant_args.get("sigma_reg", 0.025) * H.diagonal().mean()) |
| continue |
| except Exception as e: |
| if e.__class__.__name__ == "OutOfMemoryError" or "CUDA out of memory" in str(e) \ |
| or "HIP out of memory" in str(e): |
| retry_cpu = True |
| break |
| else: |
| raise e |
|
|
| if retry_cpu: |
| print(f" !! Out of memory on {str(H.device)}, trying CPU fallback") |
| torch.cuda.empty_cache() |
| H_cpu = H.cpu() |
| L_cpu = torch.linalg.cholesky(H_cpu) |
| H.copy_(L_cpu) |
| del L_cpu |
| L = H |
| H = H_cpu |
|
|
| DL = torch.diagonal(L.reshape(m, b, m, b), dim1=0, dim2=2).permute(2, 0, 1) |
| DL = torch.linalg.inv(DL) |
| L = L.view(n, m, b) |
| for i in range(m): |
| L[:, i, :] = L[:, i, :] @ DL[i, :, :] |
| L = L.reshape(n, n).contiguous() |
|
|
| L_block = L.view(m, b, m, b).permute(0, 2, 1, 3) |
| dr = torch.arange(m) |
| L_block[dr, dr] = torch.stack([torch.eye(b, device=L.device, dtype=H.dtype)] * m) |
| return L, H |
|
|
|
|
| def ldlq(weight, L, quant_args): |
| """Verbatim quantize.py ldlq() (v0.0.43): blocked (buf_size_k=128) LDLQ with |
| error feedback — 16-row blocks quantized bottom-up, compensation from the |
| LDL factor, cross-span error carried in prod_cache. ProgressBar removed; |
| quantize_tiles_multigpu -> quantize_tiles_batched (single device; asserted |
| bit-identical to the reference kernel wrapper by the worker self-checks).""" |
| torch, _ = _lazy_torch() |
| devices = quant_args["devices"] |
| for device in devices: |
| torch.cuda.synchronize(device) |
| main_stream = get_quant_stream(devices[0]) |
| with torch.cuda.stream(main_stream): |
| device = L.device |
| assert device == torch.device(devices[0]) |
|
|
| buffer_device = weight.device |
| size_k, size_n = weight.shape |
| assert size_k % 16 == 0 |
| assert size_n % 128 == 0 |
| tiles_k = size_k // 16 |
| tiles_n = size_n // 16 |
|
|
| buf_size_k = max(quant_args.get("buf_size_k", 128), 16) |
| assert buf_size_k % 16 == 0 |
| assert size_n % buf_size_k == 0 |
|
|
| prod_cache = torch.zeros((size_k, size_n), dtype=torch.float, device=device) |
| weight_q = torch.zeros((size_k, size_n), dtype=torch.float, device=buffer_device) |
| encoded = torch.zeros((tiles_k, tiles_n, 256), dtype=torch.short, device=buffer_device) |
|
|
| for j in range(size_k, 0, -buf_size_k): |
| i = j - buf_size_k |
|
|
| b_weight = weight[i:j].to(device) |
| b_weight_q = weight_q[i:j] if device == buffer_device else \ |
| torch.zeros_like(weight_q[i:j], device=device) |
| b_encoded = encoded[i // 16: j // 16] if device == buffer_device else \ |
| torch.zeros_like(encoded[i // 16: j // 16], device=device) |
| b_prod_cache = prod_cache[i:j] |
| b_L = L[i:j] |
|
|
| for bj in range(buf_size_k, 0, -16): |
| bi = bj - 16 |
|
|
| |
| bb_err = b_weight[bj:] - b_weight_q[bj:] |
| |
| bb_L = b_L[bj:, i + bi:i + bj] |
| |
| compensation_term = b_prod_cache[bi:bj] |
| compensation_term.addmm_(bb_L.T, bb_err, alpha=1.0, beta=1.0) |
| rows = b_weight[bi:bj] + compensation_term |
|
|
| tiles = rows.reshape(16, tiles_n, 16).permute(1, 0, 2).reshape(tiles_n, 256) |
| tiles = tiles[:, tensor_core_perm(device)] |
| quant_w, quant_i = quantize_tiles_batched(tiles, quant_args) |
| quant_w = quant_w[:, tensor_core_perm_i(device)] |
| quant_w = quant_w.reshape(tiles_n, 16, 16).permute(1, 0, 2).reshape(16, size_n) |
| b_weight_q[bi:bj] = quant_w |
| b_encoded[bi // 16: bj // 16] = quant_i.unsqueeze(0) |
|
|
| if device != buffer_device: |
| weight_q[i:j] = b_weight_q.to(buffer_device) |
| encoded[i // 16: j // 16] = b_encoded.to(buffer_device) |
|
|
| |
| b_err = b_weight - b_weight_q |
| prod_cache.addmm_(b_L.T, b_err, alpha=1.0, beta=1.0) |
|
|
| for device in devices: |
| torch.cuda.synchronize(device) |
|
|
| return weight_q, encoded |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| class LDLQWalk: |
| """One slice's ldlq() as a stepped state machine (verbatim v2 math).""" |
|
|
| __slots__ = ("ctx", "weight", "L", "weight_q", "encoded", "prod_cache", |
| "size_k", "size_n", "tiles_k", "tiles_n", "buf", "j", "bj", |
| "perm", "perm_i", "done") |
|
|
| def __init__(self, ctx): |
| torch, _ = _lazy_torch() |
| weight, L, quant_args = ctx["weight_r"], ctx["L"], ctx["quant_args"] |
| device = L.device |
| assert device == torch.device(quant_args["devices"][0]) |
| assert weight.device == device, "lockstep requires weight and L on one device" |
| size_k, size_n = weight.shape |
| assert size_k % 16 == 0 |
| assert size_n % 128 == 0 |
| buf = max(quant_args.get("buf_size_k", 128), 16) |
| assert buf % 16 == 0 |
| assert size_n % buf == 0 and size_k % buf == 0 |
| self.ctx = ctx |
| self.weight = weight |
| self.L = L |
| self.size_k, self.size_n = size_k, size_n |
| self.tiles_k, self.tiles_n = size_k // 16, size_n // 16 |
| self.buf = buf |
| self.prod_cache = torch.zeros((size_k, size_n), dtype=torch.float, device=device) |
| self.weight_q = torch.zeros((size_k, size_n), dtype=torch.float, device=device) |
| self.encoded = torch.zeros((self.tiles_k, self.tiles_n, 256), |
| dtype=torch.short, device=device) |
| self.perm = tensor_core_perm(device) |
| self.perm_i = tensor_core_perm_i(device) |
| self.j = size_k |
| self.bj = buf |
| self.done = False |
|
|
| def prepare(self): |
| """Verbatim v2 ldlq() inner-iteration head for block [bi,bj) of span |
| [i,j): in-place compensation addmm_ + tile gather/permute. Returns |
| this walk's [tiles_n, 256] fp32 tile rows for the batched call.""" |
| j = self.j |
| i = j - self.buf |
| bj = self.bj |
| bi = bj - 16 |
| b_weight = self.weight[i:j] |
| b_weight_q = self.weight_q[i:j] |
| b_prod_cache = self.prod_cache[i:j] |
| b_L = self.L[i:j] |
| |
| bb_err = b_weight[bj:] - b_weight_q[bj:] |
| |
| bb_L = b_L[bj:, i + bi:i + bj] |
| |
| compensation_term = b_prod_cache[bi:bj] |
| compensation_term.addmm_(bb_L.T, bb_err, alpha=1.0, beta=1.0) |
| rows = b_weight[bi:bj] + compensation_term |
| tiles = rows.reshape(16, self.tiles_n, 16).permute(1, 0, 2).reshape(self.tiles_n, 256) |
| tiles = tiles[:, self.perm] |
| return tiles |
|
|
| def commit(self, quant_w, quant_i): |
| """Verbatim v2 ldlq() inner-iteration tail: un-permute, store, and at |
| span end run the cross-span error-feedback addmm_ and advance.""" |
| j = self.j |
| i = j - self.buf |
| bj = self.bj |
| bi = bj - 16 |
| quant_w = quant_w[:, self.perm_i] |
| quant_w = quant_w.reshape(self.tiles_n, 16, 16).permute(1, 0, 2).reshape(16, self.size_n) |
| self.weight_q[i + bi:i + bj] = quant_w |
| self.encoded[(i + bi) // 16:(i + bj) // 16] = quant_i.unsqueeze(0) |
| self.bj -= 16 |
| if self.bj == 0: |
| |
| b_err = self.weight[i:j] - self.weight_q[i:j] |
| self.prod_cache.addmm_(self.L[i:j].T, b_err, alpha=1.0, beta=1.0) |
| self.j -= self.buf |
| self.bj = self.buf |
| if self.j == 0: |
| self.done = True |
| self.ctx["wq_reg"] = self.weight_q |
| self.ctx["encoded"] = self.encoded |
| return self.done |
|
|
|
|
| def lockstep_ldlq(walks, n_max, logfile=None): |
| """Advance up to n_max LDLQ walks in lockstep with ONE quantize_tiles call |
| per step (see block comment above for the bit-exactness argument). Same |
| stream/sync discipline as v2 ldlq(): sync all devices, run every op on the |
| cached quant stream, sync again before returning.""" |
| torch, _ = _lazy_torch() |
| if not walks: |
| return |
| qa = walks[0].ctx["quant_args"] |
| for w in walks: |
| wq = w.ctx["quant_args"] |
| assert wq["K"] == qa["K"] and ("mcg" in wq) == ("mcg" in qa) \ |
| and ("mul1" in wq) == ("mul1" in qa) and wq["devices"] == qa["devices"], \ |
| "lockstep pool requires uniform quantizer args" |
| devices = qa["devices"] |
| for device in devices: |
| torch.cuda.synchronize(device) |
| main_stream = get_quant_stream(devices[0]) |
| with torch.cuda.stream(main_stream): |
| pending = list(walks) |
| active = [] |
| while pending or active: |
| while pending and len(active) < n_max: |
| active.append(pending.pop(0)) |
| parts = [w.prepare() for w in active] |
| tiles = torch.cat(parts, dim=0) if len(parts) > 1 else parts[0] |
| q_w, q_i = quantize_tiles_batched(tiles, qa) |
| off = 0 |
| nxt = [] |
| for w, p in zip(active, parts): |
| m = p.shape[0] |
| w.commit(q_w[off:off + m], q_i[off:off + m]) |
| off += m |
| if not w.done: |
| nxt.append(w) |
| assert off == tiles.shape[0] |
| active = nxt |
| for device in devices: |
| torch.cuda.synchronize(device) |
|
|
|
|
| def resolve_lockstep(val) -> int: |
| """--lockstep: 'auto' -> 3*TP = 12, i.e. all slice-walks of one expert |
| co-stepped (8 gate/up walks x 32 tiles + 4 down walks x 384 tiles; the |
| steady-state gate/up phase gathers 256 tiles vs the 296-slot wave). |
| Integer N > 12 pools ceil(N/12) experts' walks together.""" |
| if isinstance(val, int): |
| n = val |
| elif str(val).strip().lower() == "auto": |
| return 3 * TP |
| else: |
| n = int(val) |
| assert n >= 1, f"--lockstep must be >= 1 or 'auto' (got {val!r})" |
| return n |
|
|
|
|
| import threading |
| finalize_capture_H_mutex = threading.Lock() |
|
|
|
|
| def finalize_capture_H(H_data, quant_args, verbose=False): |
| """Verbatim quantize.py finalize_capture_H() (v0.0.43): mean over captured |
| rows, sigma_reg diagonal damping, su sign draw (shared by all linears using |
| this H_data), su/128-Hadamard transform of H, block LDL with zeroed |
| diagonal. Returns (q_fallback, H, L, su, H_diag).""" |
| torch, _ = _lazy_torch() |
| with finalize_capture_H_mutex: |
|
|
| if H_data["H"].is_meta: |
| H_data["L"] = None |
| H_data["finalized"] = True |
| H_data["diag"] = None |
| H_data["q_fallback"] = True |
| H = H_data["H"] |
| k = H.shape[0] |
| su = (torch.randn(k, device=H_data["device"]).sign() + 1e-5).sign().to(torch.float).unsqueeze(1) |
| H_data["su"] = su |
| return True, None, None, su, None |
|
|
| if "H_swap_device" in H_data: |
| H_data["H"] = H_data["H"].to(H_data["H_swap_device"]) |
| del H_data["H_swap_device"] |
|
|
| H = H_data["H"] |
| if H_data["finalized"]: |
| return H_data["q_fallback"], H, H_data["L"], H_data["su"], H_data["diag"] |
|
|
| |
| |
| count = H_data["count"] |
| if count == 0: |
| q_fallback = True |
| diag_mean = 0.0 |
| else: |
| H /= count |
| diag_mean = torch.diag(H).mean() |
| q_fallback = diag_mean.item() < 1e-20 |
|
|
| |
| H.diagonal().add_(quant_args.get("sigma_reg", 0.025) * diag_mean) |
| diag = H.diagonal().clone() |
|
|
| |
| |
| k = H.shape[0] |
| su = (torch.randn(k, device=H.device).sign() + 1e-5).sign().to(torch.float).unsqueeze(1) |
| H_data["su"] = su |
|
|
| |
| H *= su.T |
| blockwise_preapply_had_r_(H, HAD_K) |
| H *= su |
| blockwise_preapply_had_l_(H, HAD_K) |
|
|
| |
| if q_fallback: |
| L = None |
| else: |
| L, H = block_ldl(H, 16, quant_args, verbose) |
| dr = torch.arange(k) |
| L[dr, dr] = 0 |
|
|
| H_data["L"] = L |
| H = H.cpu() |
| H_data["H"] = H.cpu() |
| H_data["finalized"] = True |
| H_data["diag"] = diag |
| H_data["q_fallback"] = q_fallback |
| return q_fallback, H, L, su, diag |
|
|
|
|
| def block_trace(A, B, block_size=1024): |
| """Verbatim inner helper of quantize_exl3() metrics: trace(A^T B A) summed |
| in blocks (A: [k, n], B: [k, k]).""" |
| torch, _ = _lazy_torch() |
| total = 0.0 |
| for j_start in range(0, B.shape[1], block_size): |
| j_end = min(j_start + block_size, B.shape[1]) |
| B_block = B[:, j_start:j_end] |
| A_j_block = A[j_start:j_end, :] |
| partial = torch.einsum("ik,ij,jk->", A, B_block, A_j_block) |
| total += partial.item() |
| return total |
|
|
|
|
| def pack_trellis(encoded, quant_args): |
| torch, ext = _lazy_torch() |
| K = quant_args["K"] |
| shape = encoded.shape |
| assert len(shape) == 3 and shape[2] == 256 and encoded.dtype == torch.int16 |
| packed = torch.zeros((shape[0], shape[1], 256 * K // 16), |
| dtype=torch.int16, device=encoded.device) |
| ext.pack_trellis(packed, encoded.contiguous(), K) |
| return packed |
|
|
|
|
| |
| |
| |
| |
|
|
| def trellis_quant_all_tiles(weight_r, quant_args): |
| """Identity-Hessian quantization of the full tensor in one batch. |
| With H=I there is no LDLQ error feedback, so every 16-row block is |
| independent — bit-identical to the reference fallback_quant() loop |
| (asserted by self_check_reference once per worker).""" |
| torch, _ = _lazy_torch() |
| k, n = weight_r.shape |
| tk, tn = k // 16, n // 16 |
| perm = tensor_core_perm(weight_r.device) |
| perm_i = tensor_core_perm_i(weight_r.device) |
| tiles = (weight_r.view(tk, 16, tn, 16).permute(0, 2, 1, 3) |
| .reshape(tk * tn, 256))[:, perm].contiguous() |
| q_tiles, q_idx = quantize_tiles_batched(tiles, quant_args) |
| wq = (q_tiles[:, perm_i].view(tk, tn, 16, 16).permute(0, 2, 1, 3) |
| .reshape(k, n).contiguous()) |
| encoded = q_idx.view(tk, tn, 256).contiguous() |
| return wq, encoded |
|
|
|
|
| def reference_fallback_quant(weight_r, quant_args): |
| """Verbatim inner loop of quantize.py fallback_quant() (streams removed): |
| used once per worker to assert trellis_quant_all_tiles is bit-identical.""" |
| torch, _ = _lazy_torch() |
| device = weight_r.device |
| size_k, size_n = weight_r.shape |
| tiles_k, tiles_n = size_k // 16, size_n // 16 |
| buf_size_k = max(quant_args.get("buf_size_k", 128), 16) |
| assert buf_size_k % 16 == 0 and size_n % buf_size_k == 0 |
| perm = tensor_core_perm(device) |
| perm_i = tensor_core_perm_i(device) |
| weight_q = torch.zeros((size_k, size_n), dtype=torch.float, device=device) |
| encoded = torch.zeros((tiles_k, tiles_n, 256), dtype=torch.short, device=device) |
| for j in range(size_k, 0, -buf_size_k): |
| i = j - buf_size_k |
| b_weight = weight_r[i:j] |
| for bj in range(buf_size_k, 0, -16): |
| bi = bj - 16 |
| rows = b_weight[bi:bj] |
| tiles = rows.reshape(16, tiles_n, 16).permute(1, 0, 2).reshape(tiles_n, 256) |
| tiles = tiles[:, perm] |
| quant_w, quant_i = quantize_tiles_batched(tiles, quant_args) |
| quant_w = quant_w[:, perm_i] |
| quant_w = quant_w.reshape(tiles_n, 16, 16).permute(1, 0, 2).reshape(16, size_n) |
| weight_q[i + bi:i + bj] = quant_w |
| encoded[(i + bi) // 16:(i + bj) // 16] = quant_i.unsqueeze(0) |
| return weight_q, encoded |
|
|
|
|
| _self_checked = False |
| _self_checked_ldlq0 = False |
| _self_checked_lockstep = False |
|
|
|
|
| def encode_slice(w_slice, H_data, seed, out_scales, logfile=None, self_check=False): |
| """Encode one (k, n) float32 CUDA tensor (exl3 convention: k=in_features, |
| n=out_features) at BITS bpw with the CALIBRATED LDLQ path, mirroring |
| exllamav3 v0.0.43 quantize_exl3() step for step. |
| |
| H_data: dict as built by make_H_data() — H = SUM of x x^T over calibration |
| rows (fp32 [k,k] CUDA), count = rows. May be SHARED between slices with |
| identical inputs (all 8 gate/up slices of an expert): the first encode |
| finalizes it (draws su, transforms H, computes the block LDL); subsequent |
| encodes reuse the cached factorization and su, drawing only their own sv — |
| exactly the reference behavior for linears sharing a qmap. |
| |
| Returns (out: dict of cpu tensors {suh, svh, trellis}, stats dict). |
| Raises AssertionError on any exactness failure (exact-or-bug).""" |
| global _self_checked, _self_checked_ldlq0 |
| torch, ext = _lazy_torch() |
| k, n = w_slice.shape |
| assert w_slice.dtype == torch.float32 and w_slice.is_cuda |
| assert k % HAD_K == 0 and n % HAD_N == 0 and n % 128 == 0 |
| assert H_data["H"].is_meta or tuple(H_data["H"].shape) == (k, k), \ |
| f"H shape {tuple(H_data['H'].shape)} != ({k},{k})" |
| device = w_slice.device |
|
|
| quant_args = {"K": BITS, "devices": [0], "apply_out_scales": out_scales, |
| "mcg": True, "sigma_reg": SIGMA_REG} |
|
|
| |
| torch.manual_seed(seed) |
| q_fallback, H, L, su, H_diag = finalize_capture_H(H_data, quant_args, verbose=False) |
| if H is not None and not H.is_cuda: |
| H = H.to(device) |
| if L is not None and not L.is_cuda: |
| L = L.to(device) |
| if su.device != device: |
| su = su.to(device) |
| if H_diag is not None and H_diag.device != device: |
| H_diag = H_diag.to(device) |
| sv = (torch.randn(n, device=device).sign() + 1e-5).sign().to(torch.float).unsqueeze(0) |
| |
| if H_data.get("L") is not None and H_data["L"].is_cuda: |
| H_data["L"] = H_data["L"].cpu() |
|
|
| w_orig = w_slice |
| apply_out_scales, weight_r, g_scale, su, sv = regularize( |
| w_slice.clone(), su, sv, quant_args, H_diag=H_diag, q_fallback=q_fallback) |
|
|
| if not q_fallback: |
| |
| |
| |
| if self_check and not _self_checked_ldlq0: |
| wq_a, enc_a = ldlq(weight_r, torch.zeros_like(L), quant_args) |
| wq_b, enc_b = trellis_quant_all_tiles(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "ldlq(L=0) vs batched: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "ldlq(L=0) vs batched: reconstructed values differ" |
| wq_c, enc_c = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_c) and torch.equal(wq_a, wq_c), \ |
| "batched vs reference fallback loop differ" |
| _self_checked_ldlq0 = True |
| _self_checked = True |
| log("self-check PASSED: ldlq(L=0) == batched tile quant == reference fallback loop", logfile) |
| wq_reg, encoded = ldlq(weight_r, L, quant_args) |
| else: |
| |
| |
| if self_check and not _self_checked: |
| wq_a, enc_a = trellis_quant_all_tiles(weight_r, quant_args) |
| wq_b, enc_b = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "batched vs reference: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "batched vs reference: reconstructed values differ" |
| _self_checked = True |
| log("self-check PASSED: batched tile quant is bit-identical to reference fallback_quant", logfile) |
| wq_reg, encoded = wq_a, enc_a |
| else: |
| wq_reg, encoded = trellis_quant_all_tiles(weight_r, quant_args) |
|
|
| |
| if not q_fallback: |
| E = weight_r - wq_reg |
| num = block_trace(E, H) |
| den = block_trace(weight_r, H) |
| proxy_err = num / max(den, 1e-8) |
| del E |
| else: |
| proxy_err = (weight_r - wq_reg).square().mean().item() |
|
|
| |
| packed = pack_trellis(encoded, quant_args) |
| unpacked = torch.zeros_like(encoded) |
| ext.unpack_trellis(unpacked, packed, BITS) |
| assert torch.equal(unpacked, encoded), "pack/unpack round-trip mismatch (format bug)" |
| w_dec = torch.empty((k, n), dtype=torch.half, device=packed.device) |
| ext.reconstruct(w_dec, packed, BITS, True, False) |
| assert torch.equal(w_dec, wq_reg.half()), \ |
| "ext.reconstruct != encoder values (codebook/packing bug)" |
| expected_bytes = k * n * BITS // 8 |
| assert packed.numel() * 2 == expected_bytes, "trellis size != exact 3.0 bpw" |
|
|
| |
| wq = preapply_had_l(wq_reg, HAD_K) |
| wq *= su |
| wq = preapply_had_r(wq, HAD_N) |
| wq *= sv |
| sse = (wq - w_orig).double().pow(2).sum().item() |
| ss = w_orig.double().pow(2).sum().item() |
|
|
| out = { |
| "suh": su.flatten().contiguous().to(dtype=torch.half).cpu(), |
| "svh": sv.flatten().contiguous().to(dtype=torch.half).cpu(), |
| "trellis": packed.cpu(), |
| } |
| stats = {"sse": sse, "ss": ss, "nmse": sse / max(ss, 1e-30), "g_scale": g_scale, |
| "proxy_err": proxy_err, "q_fallback": bool(q_fallback), |
| "apply_out_scales": bool(apply_out_scales) if apply_out_scales is not None else None} |
| return out, stats |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| def encode_slice_prologue(w_slice, H_data, seed, out_scales, logfile=None, self_check=False): |
| """First half of encode_slice() (v2-verbatim math): seed -> finalize -> |
| sv draw -> regularize (incl. per-slice g_scale_gss, UNCHANGED per owner |
| mandate). Returns a ctx dict; when ctx["wq_reg"] is None the slice still |
| needs its LDLQ main pass (run it as an LDLQWalk inside lockstep_ldlq), |
| otherwise it was completed inline (reference q_fallback branch).""" |
| global _self_checked, _self_checked_ldlq0 |
| torch, ext = _lazy_torch() |
| k, n = w_slice.shape |
| assert w_slice.dtype == torch.float32 and w_slice.is_cuda |
| assert k % HAD_K == 0 and n % HAD_N == 0 and n % 128 == 0 |
| assert H_data["H"].is_meta or tuple(H_data["H"].shape) == (k, k), \ |
| f"H shape {tuple(H_data['H'].shape)} != ({k},{k})" |
| device = w_slice.device |
|
|
| quant_args = {"K": BITS, "devices": [0], "apply_out_scales": out_scales, |
| "mcg": True, "sigma_reg": SIGMA_REG} |
|
|
| |
| torch.manual_seed(seed) |
| q_fallback, H, L, su, H_diag = finalize_capture_H(H_data, quant_args, verbose=False) |
| if H is not None and not H.is_cuda: |
| H = H.to(device) |
| if L is not None and not L.is_cuda: |
| L = L.to(device) |
| if su.device != device: |
| su = su.to(device) |
| if H_diag is not None and H_diag.device != device: |
| H_diag = H_diag.to(device) |
| sv = (torch.randn(n, device=device).sign() + 1e-5).sign().to(torch.float).unsqueeze(0) |
| |
| if H_data.get("L") is not None and H_data["L"].is_cuda: |
| H_data["L"] = H_data["L"].cpu() |
|
|
| w_orig = w_slice |
| apply_out_scales, weight_r, g_scale, su, sv = regularize( |
| w_slice.clone(), su, sv, quant_args, H_diag=H_diag, q_fallback=q_fallback) |
|
|
| wq_reg, encoded = None, None |
| if not q_fallback: |
| |
| |
| if self_check and not _self_checked_ldlq0: |
| wq_a, enc_a = ldlq(weight_r, torch.zeros_like(L), quant_args) |
| wq_b, enc_b = trellis_quant_all_tiles(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "ldlq(L=0) vs batched: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "ldlq(L=0) vs batched: reconstructed values differ" |
| wq_c, enc_c = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_c) and torch.equal(wq_a, wq_c), \ |
| "batched vs reference fallback loop differ" |
| _self_checked_ldlq0 = True |
| _self_checked = True |
| log("self-check PASSED: ldlq(L=0) == batched tile quant == reference fallback loop", logfile) |
| |
| else: |
| |
| |
| if self_check and not _self_checked: |
| wq_a, enc_a = trellis_quant_all_tiles(weight_r, quant_args) |
| wq_b, enc_b = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "batched vs reference: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "batched vs reference: reconstructed values differ" |
| _self_checked = True |
| log("self-check PASSED: batched tile quant is bit-identical to reference fallback_quant", logfile) |
| wq_reg, encoded = wq_a, enc_a |
| else: |
| wq_reg, encoded = trellis_quant_all_tiles(weight_r, quant_args) |
|
|
| return {"k": k, "n": n, "device": device, "quant_args": quant_args, |
| "q_fallback": q_fallback, "H": H, "L": L, "H_diag": H_diag, |
| "su": su, "sv": sv, "g_scale": g_scale, |
| "apply_out_scales": apply_out_scales, "w_orig": w_orig, |
| "weight_r": weight_r, "wq_reg": wq_reg, "encoded": encoded} |
|
|
|
|
| def encode_slice_epilogue(ctx): |
| """Second half of encode_slice() — verbatim v2 math from the proxy metric |
| onward (block_trace, pack/unpack/reconstruct exactness asserts, exact-bpw |
| check, weight-domain RT error, output tensors).""" |
| torch, ext = _lazy_torch() |
| k, n = ctx["k"], ctx["n"] |
| weight_r, wq_reg, encoded = ctx["weight_r"], ctx["wq_reg"], ctx["encoded"] |
| assert wq_reg is not None and encoded is not None, \ |
| "epilogue called before the slice's LDLQ walk completed" |
| H, su, sv = ctx["H"], ctx["su"], ctx["sv"] |
| q_fallback, quant_args = ctx["q_fallback"], ctx["quant_args"] |
| w_orig, g_scale = ctx["w_orig"], ctx["g_scale"] |
| apply_out_scales = ctx["apply_out_scales"] |
|
|
| |
| if not q_fallback: |
| E = weight_r - wq_reg |
| num = block_trace(E, H) |
| den = block_trace(weight_r, H) |
| proxy_err = num / max(den, 1e-8) |
| del E |
| else: |
| proxy_err = (weight_r - wq_reg).square().mean().item() |
|
|
| |
| packed = pack_trellis(encoded, quant_args) |
| unpacked = torch.zeros_like(encoded) |
| ext.unpack_trellis(unpacked, packed, BITS) |
| assert torch.equal(unpacked, encoded), "pack/unpack round-trip mismatch (format bug)" |
| w_dec = torch.empty((k, n), dtype=torch.half, device=packed.device) |
| ext.reconstruct(w_dec, packed, BITS, True, False) |
| assert torch.equal(w_dec, wq_reg.half()), \ |
| "ext.reconstruct != encoder values (codebook/packing bug)" |
| expected_bytes = k * n * BITS // 8 |
| assert packed.numel() * 2 == expected_bytes, "trellis size != exact 3.0 bpw" |
|
|
| |
| wq = preapply_had_l(wq_reg, HAD_K) |
| wq *= su |
| wq = preapply_had_r(wq, HAD_N) |
| wq *= sv |
| sse = (wq - w_orig).double().pow(2).sum().item() |
| ss = w_orig.double().pow(2).sum().item() |
|
|
| out = { |
| "suh": su.flatten().contiguous().to(dtype=torch.half).cpu(), |
| "svh": sv.flatten().contiguous().to(dtype=torch.half).cpu(), |
| "trellis": packed.cpu(), |
| } |
| stats = {"sse": sse, "ss": ss, "nmse": sse / max(ss, 1e-30), "g_scale": g_scale, |
| "proxy_err": proxy_err, "q_fallback": bool(q_fallback), |
| "apply_out_scales": bool(apply_out_scales) if apply_out_scales is not None else None} |
| return out, stats |
|
|
|
|
| def encode_slice_prologue_pre(w_slice, H_data, seed, out_scales, logfile=None): |
| """v3.1: first part of encode_slice_prologue() (v2-verbatim math): seed -> |
| finalize (su on first use of a shared H) -> sv draw -> regularize_pre |
| (out-scale decision, su/sv scaling, Hadamard transforms; g_scale NOT yet |
| applied). The per-slice g_scale search then runs POOLED across slices |
| (g_scale_gss_lockstep) before encode_slice_prologue_post(). RNG contract |
| unchanged from v2/v3: every draw happens HERE under torch.manual_seed(seed) |
| with seeds derived from (L, E, proj, r); the pooled search and _post |
| consume no RNG, so results are independent of pool scheduling.""" |
| torch, ext = _lazy_torch() |
| k, n = w_slice.shape |
| assert w_slice.dtype == torch.float32 and w_slice.is_cuda |
| assert k % HAD_K == 0 and n % HAD_N == 0 and n % 128 == 0 |
| assert H_data["H"].is_meta or tuple(H_data["H"].shape) == (k, k), \ |
| f"H shape {tuple(H_data['H'].shape)} != ({k},{k})" |
| device = w_slice.device |
|
|
| quant_args = {"K": BITS, "devices": [0], "apply_out_scales": out_scales, |
| "mcg": True, "sigma_reg": SIGMA_REG} |
|
|
| |
| torch.manual_seed(seed) |
| q_fallback, H, L, su, H_diag = finalize_capture_H(H_data, quant_args, verbose=False) |
| if H is not None and not H.is_cuda: |
| H = H.to(device) |
| if L is not None and not L.is_cuda: |
| L = L.to(device) |
| if su.device != device: |
| su = su.to(device) |
| if H_diag is not None and H_diag.device != device: |
| H_diag = H_diag.to(device) |
| sv = (torch.randn(n, device=device).sign() + 1e-5).sign().to(torch.float).unsqueeze(0) |
| |
| if H_data.get("L") is not None and H_data["L"].is_cuda: |
| H_data["L"] = H_data["L"].cpu() |
|
|
| w_orig = w_slice |
| apply_out_scales, weight_r, su, sv = regularize_pre( |
| w_slice.clone(), su, sv, quant_args, H_diag=H_diag, q_fallback=q_fallback) |
|
|
| return {"k": k, "n": n, "device": device, "quant_args": quant_args, |
| "q_fallback": q_fallback, "H": H, "L": L, "H_diag": H_diag, |
| "su": su, "sv": sv, "g_scale": None, |
| "apply_out_scales": apply_out_scales, "w_orig": w_orig, |
| "weight_r": weight_r, "wq_reg": None, "encoded": None} |
|
|
|
|
| def encode_slice_prologue_post(ctx, logfile=None, self_check=False): |
| """v3.1: rest of encode_slice_prologue() after the pooled g_scale search: |
| apply g_scale (verbatim regularize tail), then the verbatim self-check / |
| q_fallback branch. Returns the same ctx shape v3's prologue returned; |
| when ctx["wq_reg"] is None the slice still needs its LDLQ main pass.""" |
| global _self_checked, _self_checked_ldlq0 |
| torch, ext = _lazy_torch() |
| assert ctx["g_scale"] is not None, \ |
| "prologue_post called before the pooled g_scale search set ctx['g_scale']" |
| weight_r, su = regularize_post(ctx["weight_r"], ctx["su"], ctx["g_scale"]) |
| ctx["weight_r"], ctx["su"] = weight_r, su |
| L, q_fallback, quant_args = ctx["L"], ctx["q_fallback"], ctx["quant_args"] |
|
|
| wq_reg, encoded = None, None |
| if not q_fallback: |
| |
| |
| if self_check and not _self_checked_ldlq0: |
| wq_a, enc_a = ldlq(weight_r, torch.zeros_like(L), quant_args) |
| wq_b, enc_b = trellis_quant_all_tiles(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "ldlq(L=0) vs batched: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "ldlq(L=0) vs batched: reconstructed values differ" |
| wq_c, enc_c = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_c) and torch.equal(wq_a, wq_c), \ |
| "batched vs reference fallback loop differ" |
| _self_checked_ldlq0 = True |
| _self_checked = True |
| log("self-check PASSED: ldlq(L=0) == batched tile quant == reference fallback loop", logfile) |
| |
| else: |
| |
| |
| if self_check and not _self_checked: |
| wq_a, enc_a = trellis_quant_all_tiles(weight_r, quant_args) |
| wq_b, enc_b = reference_fallback_quant(weight_r, quant_args) |
| assert torch.equal(enc_a, enc_b), "batched vs reference: encoded indices differ" |
| assert torch.equal(wq_a, wq_b), "batched vs reference: reconstructed values differ" |
| _self_checked = True |
| log("self-check PASSED: batched tile quant is bit-identical to reference fallback_quant", logfile) |
| wq_reg, encoded = wq_a, enc_a |
| else: |
| wq_reg, encoded = trellis_quant_all_tiles(weight_r, quant_args) |
|
|
| ctx["wq_reg"], ctx["encoded"] = wq_reg, encoded |
| return ctx |
|
|
|
|
| def lockstep_self_check(walk_ctxs, logfile=None): |
| """One-time per worker (mirrors the v2 self-check philosophy): re-run the |
| UNTOUCHED v2 ldlq() on every walk's (weight_r, L) — both read-only to the |
| walk — and assert the lockstep pool produced bit-identical encodings.""" |
| global _self_checked_lockstep |
| torch, _ = _lazy_torch() |
| for ctx in walk_ctxs: |
| wq2, enc2 = ldlq(ctx["weight_r"], ctx["L"], ctx["quant_args"]) |
| assert torch.equal(enc2, ctx["encoded"]), \ |
| "lockstep vs sequential ldlq: encoded indices differ" |
| assert torch.equal(wq2, ctx["wq_reg"]), \ |
| "lockstep vs sequential ldlq: reconstructed values differ" |
| _self_checked_lockstep = True |
| log(f"self-check PASSED: lockstep pool ({len(walk_ctxs)} walks) == sequential " |
| f"v2 ldlq(), bit-identical", logfile) |
|
|
|
|
| def slice_seed(L, E, proj_idx, r): |
| return (SEED_BASE * 1000003 + L * 65536 + E * 16 + proj_idx * 4 + r) & 0x7FFFFFFF |
|
|
|
|
| |
| |
| |
|
|
| def make_H_data(H_sum, count, device): |
| """Mimics exllamav3 Linear.init_H_data(True) + capture_H accumulation: |
| H = SUM over calibration rows of x x^T (fp32 CUDA [k,k]), count = rows. |
| finalize_capture_H() divides by count and mutates H in place, so callers |
| must pass an OWNED tensor (clone shared/layer-level Hessians).""" |
| return {"H": H_sum, "first_key": "slice", "count": count, |
| "finalized": False, "num_total": count, "inf_nan": None, |
| "device": device} |
|
|
|
|
| class LayerCalib: |
| """Loads one layer's capture artifacts (x.bin bf16 [N,6144], ids.bin uint8 |
| [N,8]) into RAM and serves per-expert routed-token views + fallbacks.""" |
|
|
| def __init__(self, capture_dir, L, logfile=None): |
| torch, _ = _lazy_torch() |
| import numpy as np |
| d = os.path.join(capture_dir, f"layer_{L:03d}") |
| man_path = os.path.join(d, "layer_manifest.json") |
| assert os.path.exists(man_path), \ |
| f"layer {L}: capture manifest missing ({man_path}) — run capture_hessians.py --capture first" |
| with open(man_path) as f: |
| self.manifest = json.load(f) |
| self.L = L |
| self.tokens = self.manifest["tokens"] |
| assert self.manifest["hidden"] == HIDDEN and self.manifest["x_dtype"] == "bfloat16" |
| xp = os.path.join(d, "x.bin") |
| ip = os.path.join(d, "ids.bin") |
| assert os.path.getsize(xp) == self.tokens * HIDDEN * 2, f"{xp}: size mismatch vs manifest" |
| assert os.path.getsize(ip) == self.tokens * 8, f"{ip}: size mismatch vs manifest" |
| t0 = time.time() |
| x_np = np.fromfile(xp, dtype=np.int16).reshape(self.tokens, HIDDEN) |
| self.x = torch.from_numpy(x_np).view(torch.bfloat16) |
| ids = np.fromfile(ip, dtype=np.uint8).reshape(self.tokens, 8) |
| |
| flat = ids.reshape(-1) |
| order = np.argsort(flat, kind="stable") |
| counts = np.bincount(flat, minlength=NUM_EXPERTS) |
| self._starts = np.concatenate([[0], np.cumsum(counts)]) |
| self._token_of = (order // 8).astype(np.int64) |
| self.routed_counts = counts.tolist() |
| self._H_layer_cpu = None |
| self._fallback_rows = None |
| if logfile is not None: |
| log(f"layer {L}: calib loaded — {self.tokens} tokens, routed min/max=" |
| f"{counts.min()}/{counts.max()}, cold(<{MIN_ROUTED})=" |
| f"{(counts < MIN_ROUTED).sum()} ({time.time()-t0:.1f}s)", logfile) |
|
|
| def expert_rows(self, E): |
| torch, _ = _lazy_torch() |
| return torch.from_numpy(self._token_of[self._starts[E]:self._starts[E + 1]].copy()) |
|
|
| def gather_chunks(self, rows, device, chunk=HCHUNK): |
| """Yield fp32 CUDA row blocks of x[rows].""" |
| torch, _ = _lazy_torch() |
| for s in range(0, rows.numel(), chunk): |
| sel = rows[s:s + chunk] |
| yield torch.index_select(self.x, 0, sel).to(device).float() |
|
|
| def all_rows(self): |
| torch, _ = _lazy_torch() |
| return torch.arange(self.tokens, dtype=torch.int64) |
|
|
| def fallback_rows(self): |
| """Deterministic token subsample for cold-expert down-proj Hessians.""" |
| torch, _ = _lazy_torch() |
| if self._fallback_rows is None: |
| g = torch.Generator().manual_seed(SEED_BASE ^ (self.L * 2654435761 & 0x7FFFFFFF)) |
| n = min(self.tokens, FALLBACK_ROWS) |
| self._fallback_rows = torch.randperm(self.tokens, generator=g)[:n].sort().values |
| return self._fallback_rows |
|
|
| def layer_H(self, device): |
| """Layer-level H (ALL tokens): SUM x x^T fp32 [6144,6144] + count. |
| Cached on CPU; returns a fresh owned CUDA clone per call (finalize |
| mutates its input).""" |
| torch, _ = _lazy_torch() |
| if self._H_layer_cpu is None: |
| H = torch.zeros(HIDDEN, HIDDEN, dtype=torch.float32, device=device) |
| for xc in self.gather_chunks(self.all_rows(), device): |
| H.addmm_(xc.T, xc) |
| assert torch.isfinite(H).all(), f"layer {self.L}: non-finite layer H" |
| self._H_layer_cpu = H.cpu() |
| del H |
| return self._H_layer_cpu.to(device), self.tokens |
|
|
|
|
| def build_expert_hessians(calib: "LayerCalib", E, Wg, Wu, device, min_routed): |
| """Per-expert Hessian data for one MoE expert. |
| |
| Returns (hd_gateup, hd_down[4], meta): |
| hd_gateup: ONE shared H_data (H = X_e^T X_e, [6144,6144]) for all 8 |
| gate/up slices (identical inputs -> shared H/su, reference |
| semantics). Cold expert -> layer-level H over all tokens. |
| hd_down: 4 per-slice H_datas; slice r holds the [512r,512r+512) |
| diagonal block of H_down_e = I_e^T I_e, where |
| I_e = silu(X_e Wg^T) * (X_e Wu^T) (fp32, dequantized bf16 |
| gate/up weights, GLM-5.2 swiglu: silu, no clamp). Cold |
| expert -> I over the seeded layer token subsample. |
| """ |
| torch, _ = _lazy_torch() |
| import torch.nn.functional as Fn |
| rows = calib.expert_rows(E) |
| n_e = int(rows.numel()) |
| fallback = n_e < min_routed |
|
|
| WgT = Wg.float().T.contiguous() |
| WuT = Wu.float().T.contiguous() |
|
|
| H2048 = torch.zeros(MOE_INTER, MOE_INTER, dtype=torch.float32, device=device) |
| if fallback: |
| H6144, cnt_gu = calib.layer_H(device) |
| i_rows = calib.fallback_rows() |
| else: |
| H6144 = torch.zeros(HIDDEN, HIDDEN, dtype=torch.float32, device=device) |
| cnt_gu = n_e |
| i_rows = rows |
|
|
| cnt_down = int(i_rows.numel()) |
| for xc in calib.gather_chunks(i_rows, device): |
| if not fallback: |
| H6144.addmm_(xc.T, xc) |
| inter = Fn.silu(xc @ WgT) * (xc @ WuT) |
| H2048.addmm_(inter.T, inter) |
| del inter, xc |
| del WgT, WuT |
|
|
| assert torch.isfinite(H6144).all() and torch.isfinite(H2048).all(), \ |
| f"expert {E}: non-finite Hessian accumulation" |
| hd_gateup = make_H_data(H6144, cnt_gu, device) |
| hd_down = [make_H_data(H2048[r * SLICE:(r + 1) * SLICE, |
| r * SLICE:(r + 1) * SLICE].clone(), cnt_down, device) |
| for r in range(TP)] |
| del H2048 |
| meta = {"routed": n_e, "h_fallback": fallback, "count_gu": cnt_gu, |
| "count_down": cnt_down} |
| return hd_gateup, hd_down, meta |
|
|
|
|
| def free_H_data(*hds): |
| for hd in hds: |
| for k in ("H", "L", "su", "diag"): |
| hd.pop(k, None) |
|
|
|
|
| |
| |
| |
| |
| |
|
|
| @lru_cache |
| def _fp4_lut(device): |
| torch, _ = _lazy_torch() |
| v = [0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0] |
| return torch.tensor(v + [-x for x in v], dtype=torch.float32, device=device) |
|
|
|
|
| def dequant_nvfp4(packed_u8, scale_fp8_u8, ws2: float, device): |
| """packed_u8: torch.uint8 [N, K//2] (cpu); scale u8 view of fp8e4m3 |
| [N, K//16]; ws2 float. Returns bf16 [N, K] on device.""" |
| torch, _ = _lazy_torch() |
| p = packed_u8.to(device) |
| N, Kh = p.shape |
| K = Kh * 2 |
| lo = (p & 0xF).long() |
| hi = (p >> 4).long() |
| idx = torch.stack((lo, hi), dim=-1).view(N, K) |
| w = _fp4_lut(device)[idx] |
| sc = scale_fp8_u8.to(device).view(torch.float8_e4m3fn).float() * ws2 |
| w = (w.view(N, K // 16, 16) * sc.unsqueeze(-1)).view(N, K) |
| |
| rms = w.square().mean().sqrt().item() |
| assert 1e-6 < rms < 1.0, f"NVFP4 dequant RMS implausible ({rms}) — scale convention bug" |
| return w.to(torch.bfloat16) |
|
|
|
|
| |
| |
| |
|
|
| def load_expert_bf16(src: SourceModel, L, E, proj, device, logfile): |
| torch, _ = _lazy_torch() |
| import numpy as np |
| kw = expert_key(L, E, proj, "weight") |
| ks = expert_key(L, E, proj, "weight_scale") |
| k2 = expert_key(L, E, proj, "weight_scale_2") |
| rd_w = src.reader_for(kw, logfile) |
| rd_s = src.reader_for(ks, logfile) |
| rd_2 = src.reader_for(k2, logfile) |
| dt, shape, _, _ = rd_w.tensors[kw] |
| assert dt == "U8", (kw, dt) |
| exp_shape = (MOE_INTER, HIDDEN // 2) if proj != "down_proj" else (HIDDEN, MOE_INTER // 2) |
| assert tuple(shape) == exp_shape, (kw, shape) |
| dts, sshape, _, _ = rd_s.tensors[ks] |
| assert dts == "F8_E4M3" and tuple(sshape) == (exp_shape[0], exp_shape[1] // 8), (ks, dts, sshape) |
| packed = torch.from_numpy(np.frombuffer(rd_w.read_bytes(kw), dtype=np.uint8).copy()).view(*shape) |
| scale = torch.from_numpy(np.frombuffer(rd_s.read_bytes(ks), dtype=np.uint8).copy()).view(*sshape) |
| ws2 = struct.unpack("<f", rd_2.read_bytes(k2))[0] |
| return dequant_nvfp4(packed, scale, ws2, device) |
|
|
|
|
| def expert_slices(W_bf16, proj): |
| """Yield (rank, slice_f32 (k,n) exl3-convention). gate/up: [2048,6144] |
| N-sliced by output rows; down: [6144,2048] K-sliced by input cols.""" |
| torch, _ = _lazy_torch() |
| if proj != "down_proj": |
| assert W_bf16.shape == (MOE_INTER, HIDDEN) |
| for r in range(TP): |
| sl = W_bf16[r * SLICE:(r + 1) * SLICE, :] |
| yield r, sl.transpose(0, 1).contiguous().float() |
| else: |
| assert W_bf16.shape == (HIDDEN, MOE_INTER) |
| for r in range(TP): |
| sl = W_bf16[:, r * SLICE:(r + 1) * SLICE] |
| yield r, sl.transpose(0, 1).contiguous().float() |
|
|
|
|
| def layer_paths(work, L): |
| return (os.path.join(work, f"tr3-layer-{L:03d}.safetensors"), |
| os.path.join(work, f"layer-{L:03d}.done.json")) |
|
|
|
|
| def layer_done(work, L): |
| st_path, done_path = layer_paths(work, L) |
| if not (os.path.exists(st_path) and os.path.exists(done_path)): |
| return False |
| try: |
| with open(done_path) as f: |
| d = json.load(f) |
| return d.get("file_sha256") == sha256_file(st_path) |
| except Exception: |
| return False |
|
|
|
|
| def process_layer(src: SourceModel, work: str, L: int, out_scales, capture_dir: str, |
| min_routed: int, logfile: str, lockstep_n: int = None): |
| torch, _ = _lazy_torch() |
| t0 = time.time() |
| device = "cuda:0" |
| st_path, done_path = layer_paths(work, L) |
| if lockstep_n is None: |
| lockstep_n = 3 * TP |
|
|
| calib = LayerCalib(capture_dir, L, logfile) |
| calib_tokens = calib.tokens |
| calib_sha_x = calib.manifest.get("sha256_x") |
|
|
| stash = {} |
| err_num = [0.0] * NUM_EXPERTS |
| err_den = [0.0] * NUM_EXPERTS |
| slice_nmse = {} |
| slice_proxy = {} |
| routed_count = [0] * NUM_EXPERTS |
| h_fallback_experts = [] |
| q_fallback_slices = [] |
| out_scales_on = 0 |
|
|
| group_size = max(1, (lockstep_n + 3 * TP - 1) // (3 * TP)) |
| log(f"layer {L}: lockstep={lockstep_n} walks in flight " |
| f"({group_size} expert(s) per pool), gss_lockstep=on", logfile) |
|
|
| for E0 in range(0, NUM_EXPERTS, group_size): |
| Es = list(range(E0, min(E0 + group_size, NUM_EXPERTS))) |
| te = time.time() |
| group_hd = [] |
| pre_list = [] |
| walk_ctxs = [] |
| for E in Es: |
| W = {proj: load_expert_bf16(src, L, E, proj, device, logfile) for proj in PROJS} |
| hd_gu, hd_down, hmeta = build_expert_hessians( |
| calib, E, W["gate_proj"], W["up_proj"], device, min_routed) |
| routed_count[E] = hmeta["routed"] |
| if hmeta["h_fallback"]: |
| h_fallback_experts.append(E) |
|
|
| |
| |
| |
| |
| |
| for pi, proj in enumerate(PROJS): |
| for r, sl in expert_slices(W[proj], proj): |
| hd = hd_gu if proj != "down_proj" else hd_down[r] |
| ctx = encode_slice_prologue_pre( |
| sl, hd, slice_seed(L, E, pi, r), out_scales, logfile=logfile) |
| pre_list.append((E, proj, r, ctx)) |
| del W |
| group_hd.append((hd_gu, hd_down)) |
|
|
| |
| |
| g_scale_gss_lockstep([c for _, _, _, c in pre_list], logfile, self_check=True) |
|
|
| ordered = [] |
| for E, proj, r, ctx in pre_list: |
| ctx = encode_slice_prologue_post(ctx, logfile=logfile, self_check=True) |
| ordered.append((E, proj, r, ctx)) |
| if ctx["wq_reg"] is None: |
| walk_ctxs.append(ctx) |
| del pre_list |
|
|
| |
| walks = [LDLQWalk(c) for c in walk_ctxs] |
| lockstep_ldlq(walks, lockstep_n, logfile) |
| if walks and not _self_checked_lockstep: |
| lockstep_self_check(walk_ctxs, logfile) |
| del walks |
|
|
| for E, proj, r, ctx in ordered: |
| out, stats = encode_slice_epilogue(ctx) |
| stash[(E, proj, r)] = out |
| err_num[E] += stats["sse"] |
| err_den[E] += stats["ss"] |
| key = f"{E}.{proj}.rank{r}" |
| slice_nmse[key] = stats["nmse"] |
| slice_proxy[key] = stats["proxy_err"] |
| if stats["q_fallback"]: |
| q_fallback_slices.append(key) |
| if stats["apply_out_scales"]: |
| out_scales_on += 1 |
| ctx.clear() |
| for hd_gu, hd_down in group_hd: |
| free_H_data(hd_gu, *hd_down) |
| del ordered, walk_ctxs, group_hd |
|
|
| dt_e = (time.time() - te) / len(Es) |
| for E in Es: |
| if E % 16 == 15: |
| rel = err_num[E] / max(err_den[E], 1e-30) |
| log(f"layer {L} expert {E:3d} done ({dt_e:.1f}s/expert, " |
| f"routed {routed_count[E]}, last nmse {rel:.3e})", logfile) |
|
|
| del calib |
| if q_fallback_slices: |
| log(f"layer {L} WARNING: {len(q_fallback_slices)} slices hit the reference " |
| f"q_fallback (uncalibrated) branch: {q_fallback_slices[:4]}...", logfile) |
|
|
| rel_err = [err_num[E] / max(err_den[E], 1e-30) for E in range(NUM_EXPERTS)] |
| order = sorted(range(NUM_EXPERTS), key=lambda E: rel_err[E], reverse=True) |
| keep = sorted(order[:KEEP_NVFP4]) |
| tail = [E for E in range(NUM_EXPERTS) if E not in set(keep)] |
| assert len(tail) == NUM_EXPERTS - KEEP_NVFP4 |
|
|
| entries = [] |
| mcg_bytes = struct.pack("<I", MCG_MULT) |
| for E in tail: |
| for proj in PROJS: |
| for r in range(TP): |
| t = stash[(E, proj, r)] |
| base = f"model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}" |
| tr = t["trellis"] |
| entries.append((f"{base}.suh", "F16", tuple(t["suh"].shape), |
| t["suh"].numpy().tobytes())) |
| entries.append((f"{base}.svh", "F16", tuple(t["svh"].shape), |
| t["svh"].numpy().tobytes())) |
| entries.append((f"{base}.trellis", "I16", tuple(tr.shape), |
| tr.numpy().tobytes())) |
| entries.append((f"{base}.mcg", "I32", (), mcg_bytes)) |
|
|
| _, file_sha = write_safetensors(st_path, entries, metadata={"format": "pt"}) |
| done = { |
| "layer": L, |
| "bits": BITS, |
| "codebook": "mcg", |
| "hessian": "ldlq-calibrated", |
| "sigma_reg": SIGMA_REG, |
| "min_routed": min_routed, |
| "capture": { |
| "dir": capture_dir, |
| "tokens": calib_tokens, |
| "sha256_x": calib_sha_x, |
| }, |
| "expert_routed_count": routed_count, |
| "experts_layer_h_fallback": h_fallback_experts, |
| "q_fallback_slices": q_fallback_slices, |
| "slices_with_out_scales": out_scales_on, |
| "su_scheme": "gate/up slices share one H+su per expert (su drawn under " |
| "gate.rank0 seed at first finalize, reference semantics); " |
| "down slices each own H+su under their slice seed; sv per slice", |
| "tp": TP, |
| "keep_nvfp4": keep, |
| "tail_tr3": tail, |
| "expert_rel_rt_mse": rel_err, |
| "slice_nmse": slice_nmse, |
| "slice_proxy_err": slice_proxy, |
| "seed_base": SEED_BASE, |
| "lockstep": lockstep_n, |
| "gss_lockstep": True, |
| "exllamav3": "0.0.43", |
| "file": os.path.basename(st_path), |
| "file_sha256": file_sha, |
| "encode_seconds": round(time.time() - t0, 1), |
| "finished": time.strftime("%Y-%m-%dT%H:%M:%S"), |
| } |
| tmp = done_path + ".tmp" |
| with open(tmp, "w") as f: |
| json.dump(done, f, indent=1) |
| os.replace(tmp, done_path) |
| log(f"layer {L} COMPLETE in {done['encode_seconds']}s; keep_nvfp4={keep[:8]}...", logfile) |
|
|
|
|
| |
| |
| |
|
|
| def parse_layers(spec: str): |
| out = [] |
| for part in spec.split(","): |
| part = part.strip() |
| if "-" in part: |
| a, b = part.split("-") |
| out += list(range(int(a), int(b) + 1)) |
| elif part: |
| out.append(int(part)) |
| for L in out: |
| assert FIRST_MOE_LAYER <= L < NUM_LAYERS, f"layer {L} is not a main MoE layer" |
| return sorted(set(out)) |
|
|
|
|
| def check_capture(capture_dir: str, layers) -> None: |
| """CALIBRATION IS MANDATORY: refuse to encode without a complete capture.""" |
| missing = [] |
| for L in layers: |
| d = os.path.join(capture_dir, f"layer_{L:03d}") |
| if not (os.path.exists(os.path.join(d, "layer_manifest.json")) |
| and os.path.exists(os.path.join(d, "x.bin")) |
| and os.path.exists(os.path.join(d, "ids.bin"))): |
| missing.append(L) |
| if missing: |
| raise SystemExit( |
| f"capture incomplete in {capture_dir}: layers {missing[:8]}" |
| f"{'...' if len(missing) > 8 else ''} — run capture_hessians.py --capture " |
| f"first (owner mandate: no identity-Hessian encode)") |
|
|
|
|
| def worker_main(args): |
| logfile = os.path.join(args.work, "logs", f"worker{args.worker_rank}.log") |
| os.makedirs(os.path.dirname(logfile), exist_ok=True) |
| torch, ext = _lazy_torch() |
| lockstep_n = resolve_lockstep(args.lockstep) |
| log(f"worker {args.worker_rank} up on {torch.cuda.get_device_name(0)} " |
| f"(CUDA_VISIBLE_DEVICES={os.environ.get('CUDA_VISIBLE_DEVICES')}, " |
| f"lockstep={lockstep_n})", logfile) |
| src = SourceModel(args.src) |
| layers = parse_layers(args.layers) |
| mine = layers[args.worker_rank::args.workers] |
| check_capture(args.capture_dir, mine) |
| out_scales = {"auto": None, "always": True, "never": False}[args.out_scales] |
| for L in mine: |
| if layer_done(args.work, L): |
| log(f"layer {L} already done, skipping", logfile) |
| continue |
| process_layer(src, args.work, L, out_scales, args.capture_dir, |
| args.min_routed, logfile, lockstep_n) |
| log(f"worker {args.worker_rank} finished {len(mine)} layers", logfile) |
|
|
|
|
| def orchestrate_encode(args): |
| os.makedirs(os.path.join(args.work, "logs"), exist_ok=True) |
| logfile = os.path.join(args.work, "logs", "driver.log") |
| layers = parse_layers(args.layers) |
| check_capture(args.capture_dir, layers) |
| todo = [L for L in layers if not layer_done(args.work, L)] |
| log(f"encode: {len(layers)} layers requested, {len(todo)} to do, " |
| f"{args.workers} workers, bits={BITS}, keep={KEEP_NVFP4}, tp={TP}, " |
| f"hessian=ldlq-calibrated (capture {args.capture_dir}, " |
| f"min_routed={args.min_routed}), lockstep={resolve_lockstep(args.lockstep)}", logfile) |
| if not todo: |
| log("nothing to do", logfile) |
| return |
| procs = [] |
| for r in range(args.workers): |
| env = dict(os.environ) |
| env["CUDA_VISIBLE_DEVICES"] = str(r % args.gpus) |
| cmd = [sys.executable, os.path.abspath(__file__), |
| "--worker-rank", str(r), |
| "--workers", str(args.workers), |
| "--src", args.src, "--work", args.work, |
| "--layers", args.layers, "--out-scales", args.out_scales, |
| "--capture-dir", args.capture_dir, |
| "--min-routed", str(args.min_routed), |
| "--lockstep", str(args.lockstep)] |
| p = subprocess.Popen(cmd, env=env) |
| procs.append(p) |
| log(f"spawned worker {r} pid {p.pid} on GPU {r}", logfile) |
| rc = 0 |
| try: |
| for r, p in enumerate(procs): |
| code = p.wait() |
| log(f"worker {r} exited with code {code}", logfile) |
| rc |= code |
| except KeyboardInterrupt: |
| for p in procs: |
| p.terminate() |
| raise |
| done = [L for L in layers if layer_done(args.work, L)] |
| log(f"encode pass done: {len(done)}/{len(layers)} layers complete", logfile) |
| sys.exit(1 if rc else 0) |
|
|
|
|
| |
| |
| |
|
|
| def aux_files(src_dir: str): |
| """Every non-weight file in the source repo is carried byte-exact — |
| everything except the shards, the index, and config.json (rewritten |
| with the hybrid addendum).""" |
| skip = {"model.safetensors.index.json", "config.json", "MANIFEST.sha256"} |
| out = [] |
| for fn in sorted(os.listdir(src_dir)): |
| p = os.path.join(src_dir, fn) |
| if not os.path.isfile(p) or fn in skip or fn.endswith(".safetensors"): |
| continue |
| out.append(fn) |
| return out |
|
|
|
|
| def assemble(args): |
| os.makedirs(args.out, exist_ok=True) |
| logfile = os.path.join(args.work, "logs", "assemble.log") |
| os.makedirs(os.path.dirname(logfile), exist_ok=True) |
| src = SourceModel(args.src) |
|
|
| layers = src.moe_layers() |
| dones = {} |
| for L in layers: |
| st_path, done_path = layer_paths(args.work, L) |
| assert layer_done(args.work, L), f"layer {L} not encoded/verified; run --encode first" |
| with open(done_path) as f: |
| dones[L] = json.load(f) |
| log(f"assemble: all {len(layers)} MoE layers present", logfile) |
|
|
| |
| all_src = sorted(src.weight_map.keys()) |
| dropped = set() |
| for L in layers: |
| for E in dones[L]["tail_tr3"]: |
| for proj in PROJS: |
| for sfx in ("weight", "weight_scale", "weight_scale_2"): |
| dropped.add(expert_key(L, E, proj, sfx)) |
|
|
| def carried_for_prefix(pfx): |
| return [k for k in all_src if k.startswith(pfx) and k not in dropped] |
|
|
| shard_jobs = [] |
| shard_jobs.append(("model-embed.safetensors", |
| [("src", "model.embed_tokens.weight")])) |
| head = [k for k in ("lm_head.weight", "model.norm.weight") if k in src.weight_map] |
| shard_jobs.append(("model-head.safetensors", [("src", k) for k in head])) |
| for L in range(NUM_LAYERS + 1): |
| items = [("src", k) for k in carried_for_prefix(f"model.layers.{L}.")] |
| if L in dones: |
| st_path, _ = layer_paths(args.work, L) |
| rd = STReader(st_path) |
| items += [("tr3", L, k) for k in sorted(rd.tensors.keys())] |
| shard_jobs.append((f"model-layer-{L:03d}.safetensors", items)) |
|
|
| accounted = set() |
| for _, items in shard_jobs: |
| for it in items: |
| if it[0] == "src": |
| accounted.add(it[1]) |
| missing = [k for k in all_src if k not in dropped and k not in accounted] |
| assert not missing, f"unaccounted source tensors: {missing[:5]} (+{len(missing)-5 if len(missing)>5 else 0})" |
|
|
| |
| weight_map = {} |
| total_size = 0 |
| from multiprocessing import Pool |
|
|
| job_args = [(args.src, args.work, args.out, name, items) for name, items in shard_jobs] |
| with Pool(processes=min(args.io_workers, len(job_args))) as pool: |
| results = pool.map(_assemble_shard, job_args) |
|
|
| for (name, _), (wm_part, nbytes) in zip(shard_jobs, results): |
| weight_map.update({k: name for k in wm_part}) |
| total_size += nbytes |
| log(f"assemble: wrote {len(shard_jobs)} shards, {total_size/2**30:.1f} GiB tensor payload, " |
| f"all carried tensors verified byte-exact", logfile) |
|
|
| |
| hset = {d.get("hessian") for d in dones.values()} |
| assert hset == {"ldlq-calibrated"}, f"mixed/legacy hessian modes in done JSONs: {hset}" |
| cap_infos = {json.dumps(d["capture"], sort_keys=True) for d in dones.values()} |
| assert len(cap_infos) == 1, "layers were encoded against different captures" |
| cap = dones[layers[0]]["capture"] |
| calibration = { |
| "capture_dir": cap["dir"], |
| "tokens_per_layer": cap["tokens"], |
| "min_routed_floor": dones[layers[0]]["min_routed"], |
| "sigma_reg": dones[layers[0]]["sigma_reg"], |
| "layer_h_fallback_experts_total": sum(len(d["experts_layer_h_fallback"]) |
| for d in dones.values()), |
| "q_fallback_slices_total": sum(len(d["q_fallback_slices"]) |
| for d in dones.values()), |
| } |
| cap_manifest = os.path.join(cap["dir"], "capture_manifest.json") |
| if os.path.exists(cap_manifest): |
| with open(cap_manifest) as f: |
| cm = json.load(f) |
| calibration.update({ |
| "corpus_path": cm.get("corpus_path"), |
| "corpus_sha256": cm.get("corpus_sha256"), |
| "corpus_seed": cm.get("seed"), |
| "num_samples": cm.get("num_samples"), |
| "total_tokens": cm.get("total_tokens"), |
| }) |
| import shutil |
| shutil.copyfile(cap_manifest, os.path.join(args.out, "calibration_manifest.json")) |
| log("copied calibration_manifest.json into checkpoint", logfile) |
|
|
| cfg = dict(src.config) |
| cfg["hybrid_tr3_tail"] = { |
| "producer": "encode_tr3.py", |
| "source_repo": "lukealonso/GLM-5.2-NVFP4", |
| "format": "exl3-trellis", |
| "bits": float(BITS), |
| "codebook": "mcg", |
| "mcg_multiplier": MCG_MULT, |
| "hessian": "ldlq-calibrated", |
| "calibration": calibration, |
| "exllamav3_version": "0.0.43", |
| "moe_layers": [layers[0], layers[-1]], |
| "experts_per_layer": NUM_EXPERTS, |
| "nvfp4_keep_per_layer": KEEP_NVFP4, |
| "tr3_tail_per_layer": NUM_EXPERTS - KEEP_NVFP4, |
| "tp": TP, |
| "slicing": { |
| "gate_proj": "N-sliced: rank r = output rows [512r, 512r+512) of [2048,6144]; " |
| "H = expert-routed X_e^T X_e [6144,6144], shared with up_proj", |
| "up_proj": "N-sliced: rank r = output rows [512r, 512r+512) of [2048,6144]; " |
| "H shared with gate_proj (same input)", |
| "down_proj": "K-sliced: rank r = input cols [512r, 512r+512) of [6144,2048]; " |
| "H = [512r,512r+512) diagonal block of I_e^T I_e " |
| "(I_e = silu(X_e Wg^T) * (X_e Wu^T), dequantized gate/up) — " |
| "slice-local LDLQ", |
| }, |
| "tensor_schema": "model.layers.{L}.mlp.experts.{E}.{proj}.rank{r}.{trellis|suh|svh|mcg}", |
| "selection": "per layer, 64 experts with highest pooled relative trellis RT-MSE " |
| "(measured under the calibrated LDLQ encode) kept NVFP4", |
| "tier_bitmap": "tier_bitmap.json", |
| "seed_base": SEED_BASE, |
| } |
| with open(os.path.join(args.out, "config.json"), "w") as f: |
| json.dump(cfg, f, indent=2) |
|
|
| |
| index = {"metadata": {"total_size": total_size}, "weight_map": weight_map} |
| with open(os.path.join(args.out, "model.safetensors.index.json"), "w") as f: |
| json.dump(index, f, indent=1, sort_keys=True) |
| audit_index(args.out, logfile) |
|
|
| |
| tb = {str(L): {"keep_nvfp4": dones[L]["keep_nvfp4"], |
| "expert_rel_rt_mse": dones[L]["expert_rel_rt_mse"]} for L in layers} |
| with open(os.path.join(args.out, "tier_bitmap.json"), "w") as f: |
| json.dump(tb, f) |
|
|
| |
| for fn in aux_files(args.src): |
| sp = os.path.join(args.src, fn) |
| dp = os.path.join(args.out, fn) |
| with open(sp, "rb") as fi, open(dp, "wb") as fo: |
| while True: |
| b = fi.read(CHUNK) |
| if not b: |
| break |
| fo.write(b) |
| assert sha256_file(sp) == sha256_file(dp), f"aux copy mismatch: {fn}" |
| log(f"copied {fn} (byte-exact verified)", logfile) |
|
|
| |
| names = sorted(fn for fn in os.listdir(args.out) |
| if os.path.isfile(os.path.join(args.out, fn)) and fn != "MANIFEST.sha256") |
| with open(os.path.join(args.out, "MANIFEST.sha256"), "w") as f: |
| for fn in names: |
| f.write(f"{sha256_file(os.path.join(args.out, fn))} {fn}\n") |
| log(f"assemble COMPLETE -> {args.out} ({len(names)} files + MANIFEST.sha256)", logfile) |
|
|
|
|
| def _assemble_shard(job): |
| """Pool worker: write one output shard, then re-read it and assert every |
| tensor's payload sha256 equals the source payload sha256.""" |
| src_dir, work, out, name, items = job |
| src = SourceModel(src_dir) |
| readers = {} |
|
|
| def rd(path): |
| if path not in readers: |
| readers[path] = STReader(path) |
| return readers[path] |
|
|
| entries = [] |
| src_sha = {} |
| for it in items: |
| if it[0] == "src": |
| key = it[1] |
| r = rd(os.path.join(src_dir, src.weight_map[key])) |
| dt, shape, _, _ = r.tensors[key] |
| entries.append((key, dt, shape, (lambda r=r, key=key: r.read_bytes(key)))) |
| else: |
| _, L, key = it |
| st_path, _ = layer_paths(work, L) |
| r = rd(st_path) |
| dt, shape, _, _ = r.tensors[key] |
| entries.append((key, dt, shape, (lambda r=r, key=key: r.read_bytes(key)))) |
|
|
| out_path = os.path.join(out, name) |
| written_sha, _ = write_safetensors(out_path, entries, metadata={"format": "pt"}) |
|
|
| |
| for it in items: |
| if it[0] == "src": |
| key = it[1] |
| src_sha[key] = rd(os.path.join(src_dir, src.weight_map[key])).sha256_stream(key) |
| else: |
| _, L, key = it |
| st_path, _ = layer_paths(work, L) |
| src_sha[key] = rd(st_path).sha256_stream(key) |
|
|
| |
| check = STReader(out_path) |
| nbytes = 0 |
| for key, sha in src_sha.items(): |
| dt, shape, s, e = check.tensors[key] |
| got = sha256_range(out_path, s, e) |
| assert got == sha, f"BYTE-EXACT VERIFY FAILED: {name}:{key}" |
| assert written_sha[key] == sha, f"write-path hash mismatch: {name}:{key}" |
| nbytes += e - s |
| return list(src_sha.keys()), nbytes |
|
|
|
|
| def audit_index(out: str, logfile): |
| with open(os.path.join(out, "model.safetensors.index.json")) as f: |
| index = json.load(f) |
| wm = index["weight_map"] |
| by_file = {} |
| for k, fn in wm.items(): |
| by_file.setdefault(fn, set()).add(k) |
| for fn, keys in by_file.items(): |
| p = os.path.join(out, fn) |
| assert os.path.exists(p), f"index maps to missing shard {fn}" |
| rd = STReader(p) |
| in_file = set(rd.tensors.keys()) |
| assert keys == in_file, (f"index/shard mismatch in {fn}: " |
| f"missing={list(keys-in_file)[:3]} extra={list(in_file-keys)[:3]}") |
| log(f"index audit OK: {len(wm)} tensors across {len(by_file)} shards, bijective", logfile) |
|
|
|
|
| |
| |
| |
|
|
| def upload(args): |
| token = os.environ.get("HF_TOKEN") |
| assert token, "HF_TOKEN env var not set (never pass it on the command line)" |
| from huggingface_hub import HfApi |
| api = HfApi(token=token) |
| api.create_repo(args.repo, repo_type="model", private=True, exist_ok=True) |
| for attempt in range(1, 6): |
| try: |
| api.upload_large_folder(repo_id=args.repo, folder_path=args.out, |
| repo_type="model") |
| print(f"upload complete: https://huggingface.co/{args.repo} (private)") |
| return |
| except Exception as e: |
| print(f"upload attempt {attempt}/5 failed: {type(e).__name__}: {e}") |
| time.sleep(min(60 * attempt, 300)) |
| raise SystemExit("upload failed after 5 attempts") |
|
|
|
|
| |
| |
| |
| |
| |
|
|
| def smoke(args): |
| torch, ext = _lazy_torch() |
| log(f"smoke: torch {torch.__version__}, gpu {torch.cuda.get_device_name(0)}") |
| torch.manual_seed(99) |
| for (k, n) in ((HIDDEN, SLICE), (SLICE, HIDDEN)): |
| w = torch.randn(k, n, device="cuda:0", dtype=torch.float32) * 0.02 |
| |
| X = torch.randn(8192, k, device="cuda:0", dtype=torch.float32) |
| X *= (1.0 + torch.rand(k, device="cuda:0")).unsqueeze(0) |
| H_data = make_H_data(X.T @ X, X.shape[0], "cuda:0") |
| del X |
| t0 = time.time() |
| out, stats = encode_slice(w, H_data, 1234, None, self_check=True) |
| dt = time.time() - t0 |
| assert not stats["q_fallback"], "smoke unexpectedly hit the uncalibrated branch" |
| assert out["trellis"].numel() * 2 == k * n * BITS // 8 |
| free_H_data(H_data) |
| log(f"smoke ({k}x{n}): OK (ldlq), nmse={stats['nmse']:.4e}, " |
| f"proxy_err={stats['proxy_err']:.4e}, g_scale={stats['g_scale']:.3f}, " |
| f"{dt:.2f}s (round-trip exactness asserted)") |
| |
| X = torch.randn(4096, HIDDEN, device="cuda:0", dtype=torch.float32) |
| hd = make_H_data(X.T @ X, X.shape[0], "cuda:0") |
| del X |
| w1 = torch.randn(HIDDEN, SLICE, device="cuda:0", dtype=torch.float32) * 0.02 |
| w2 = torch.randn(HIDDEN, SLICE, device="cuda:0", dtype=torch.float32) * 0.02 |
| _, s1 = encode_slice(w1, hd, 555, None) |
| assert hd["finalized"] |
| _, s2 = encode_slice(w2, hd, 556, None) |
| free_H_data(hd) |
| log(f"smoke shared-H reuse: OK (nmse {s1['nmse']:.3e} / {s2['nmse']:.3e})") |
|
|
| |
| |
| |
| |
| torch.manual_seed(101) |
| cases = [] |
| for i, (k, n) in enumerate(((HIDDEN, SLICE), (SLICE, HIDDEN))): |
| w = torch.randn(k, n, device="cuda:0", dtype=torch.float32) * 0.02 |
| X = torch.randn(8192, k, device="cuda:0", dtype=torch.float32) |
| X *= (1.0 + torch.rand(k, device="cuda:0")).unsqueeze(0) |
| Hs = X.T @ X |
| del X |
| cases.append((w, Hs, 4321 + i)) |
| ws = torch.randn(HIDDEN, SLICE, device="cuda:0", dtype=torch.float32) * 0.02 |
| ws2 = torch.randn(HIDDEN, SLICE, device="cuda:0", dtype=torch.float32) * 0.02 |
| Xs = torch.randn(4096, HIDDEN, device="cuda:0", dtype=torch.float32) |
| Hshared = Xs.T @ Xs |
| del Xs |
| |
| hds = [make_H_data(Hs.clone(), 8192, "cuda:0") for _, Hs, _ in cases] |
| hd_sh = make_H_data(Hshared.clone(), 4096, "cuda:0") |
| outs_a = [encode_slice(w, hd, seed, None)[0] |
| for (w, _, seed), hd in zip(cases, hds)] |
| outs_a.append(encode_slice(ws, hd_sh, 777, None)[0]) |
| outs_a.append(encode_slice(ws2, hd_sh, 778, None)[0]) |
| for hd in hds: |
| free_H_data(hd) |
| free_H_data(hd_sh) |
| |
| hds = [make_H_data(Hs.clone(), 8192, "cuda:0") for _, Hs, _ in cases] |
| hd_sh = make_H_data(Hshared.clone(), 4096, "cuda:0") |
| ctxs = [encode_slice_prologue(w, hd, seed, None) |
| for (w, _, seed), hd in zip(cases, hds)] |
| ctxs.append(encode_slice_prologue(ws, hd_sh, 777, None)) |
| ctxs.append(encode_slice_prologue(ws2, hd_sh, 778, None)) |
| walks = [LDLQWalk(c) for c in ctxs if c["wq_reg"] is None] |
| lockstep_ldlq(walks, 12) |
| outs_b = [encode_slice_epilogue(c)[0] for c in ctxs] |
| for hd in hds: |
| free_H_data(hd) |
| free_H_data(hd_sh) |
| names = ["6144x512", "512x6144", "sharedH-1", "sharedH-2"] |
| for name, oa, ob in zip(names, outs_a, outs_b): |
| for tname in ("trellis", "suh", "svh"): |
| assert oa[tname].numpy().tobytes() == ob[tname].numpy().tobytes(), \ |
| f"smoke lockstep mismatch: {name} {tname}" |
| log(f"smoke lockstep: OK — {len(names)} walks (mixed geometry + shared-H) " |
| f"lockstep == sequential encode_slice, byte-identical") |
|
|
| |
| |
| |
| |
| hds = [make_H_data(Hs.clone(), 8192, "cuda:0") for _, Hs, _ in cases] |
| hd_sh = make_H_data(Hshared.clone(), 4096, "cuda:0") |
| pres = [encode_slice_prologue_pre(w, hd, seed, None) |
| for (w, _, seed), hd in zip(cases, hds)] |
| pres.append(encode_slice_prologue_pre(ws, hd_sh, 777, None)) |
| pres.append(encode_slice_prologue_pre(ws2, hd_sh, 778, None)) |
| g_scale_gss_lockstep(pres, None, self_check=True) |
| ctxs = [encode_slice_prologue_post(c) for c in pres] |
| walks = [LDLQWalk(c) for c in ctxs if c["wq_reg"] is None] |
| lockstep_ldlq(walks, 12) |
| outs_c = [encode_slice_epilogue(c)[0] for c in ctxs] |
| for hd in hds: |
| free_H_data(hd) |
| free_H_data(hd_sh) |
| for name, oa, oc in zip(names, outs_a, outs_c): |
| for tname in ("trellis", "suh", "svh"): |
| assert oa[tname].numpy().tobytes() == oc[tname].numpy().tobytes(), \ |
| f"smoke v3.1 pooled-GSS mismatch: {name} {tname}" |
| log(f"smoke gss lockstep: OK — {len(names)} walks (pooled GSS pipeline) == " |
| f"sequential encode_slice, byte-identical") |
| log("smoke PASSED") |
|
|
|
|
| |
| |
| |
|
|
| def oracle(args): |
| """HARD GATE: byte-equality of the deployed v2 sequential encode_slice() |
| vs the v3 lockstep-LDLQ pipeline vs the v3.1 pooled-GSS pipeline on REAL |
| slices — dequantized source experts + real captured Hessians of ONE layer |
| (pick a layer the running encode has not reached), spanning both |
| geometries and the shared-H gate/up semantics. The expert's raw Hessian |
| sums are built once and CLONED per pass so all three passes see |
| bit-identical inputs. PASS requires v3.1 == v3 == v2 on trellis+suh+svh |
| bytes AND exact g_scale equality. Writes nothing except --oracle-log.""" |
| torch, _ = _lazy_torch() |
| olog = args.oracle_log |
| layers = parse_layers(args.layers) |
| assert len(layers) == 1, "--oracle expects exactly one layer, e.g. --layers 72" |
| L = layers[0] |
| check_capture(args.capture_dir, [L]) |
| lockstep_n = resolve_lockstep(args.lockstep) |
| out_scales = {"auto": None, "always": True, "never": False}[args.out_scales] |
| experts = [int(x) for x in args.oracle_experts.split(",")] |
| src = SourceModel(args.src) |
| log(f"ORACLE start (v3.1): layer {L}, experts {experts}, lockstep={lockstep_n}, " |
| f"gpu {torch.cuda.get_device_name(0)}, torch {torch.__version__}", olog) |
| calib = LayerCalib(args.capture_dir, L, olog) |
| device = "cuda:0" |
| total = passed = 0 |
| t_v2 = t_v3 = t_v31 = 0.0 |
| for E in experts: |
| W = {proj: load_expert_bf16(src, L, E, proj, device, olog) for proj in PROJS} |
| hd0_gu, hd0_down, hmeta = build_expert_hessians( |
| calib, E, W["gate_proj"], W["up_proj"], device, args.min_routed) |
| log(f"ORACLE E{E}: routed={hmeta['routed']} h_fallback={hmeta['h_fallback']} " |
| f"(raw H sums built once, cloned per pass)", olog) |
| snap_gu = (hd0_gu["H"].clone(), hd0_gu["count"]) |
| snap_down = [(hd["H"].clone(), hd["count"]) for hd in hd0_down] |
| free_H_data(hd0_gu, *hd0_down) |
| slices = [] |
| for pi, proj in enumerate(PROJS): |
| for r, sl in expert_slices(W[proj], proj): |
| slices.append((pi, proj, r, sl)) |
| del W |
|
|
| |
| hd_gu = make_H_data(snap_gu[0].clone(), snap_gu[1], device) |
| hd_down = [make_H_data(h.clone(), c, device) for h, c in snap_down] |
| v2_out = {} |
| torch.cuda.synchronize() |
| t1 = time.time() |
| for pi, proj, r, sl in slices: |
| hd = hd_gu if proj != "down_proj" else hd_down[r] |
| v2_out[(proj, r)] = encode_slice(sl, hd, slice_seed(L, E, pi, r), |
| out_scales, logfile=None, self_check=False) |
| torch.cuda.synchronize() |
| t_v2 += time.time() - t1 |
| free_H_data(hd_gu, *hd_down) |
|
|
| |
| hd_gu = make_H_data(snap_gu[0].clone(), snap_gu[1], device) |
| hd_down = [make_H_data(h.clone(), c, device) for h, c in snap_down] |
| torch.cuda.synchronize() |
| t1 = time.time() |
| ctxs = [] |
| for pi, proj, r, sl in slices: |
| hd = hd_gu if proj != "down_proj" else hd_down[r] |
| ctxs.append((proj, r, encode_slice_prologue( |
| sl, hd, slice_seed(L, E, pi, r), out_scales, |
| logfile=None, self_check=False))) |
| walks = [LDLQWalk(c) for _, _, c in ctxs if c["wq_reg"] is None] |
| lockstep_ldlq(walks, lockstep_n, None) |
| v3_out = {} |
| for proj, r, ctx in ctxs: |
| v3_out[(proj, r)] = encode_slice_epilogue(ctx) |
| torch.cuda.synchronize() |
| t_v3 += time.time() - t1 |
| free_H_data(hd_gu, *hd_down) |
| del walks, ctxs |
|
|
| |
| hd_gu = make_H_data(snap_gu[0].clone(), snap_gu[1], device) |
| hd_down = [make_H_data(h.clone(), c, device) for h, c in snap_down] |
| torch.cuda.synchronize() |
| t1 = time.time() |
| pres = [] |
| for pi, proj, r, sl in slices: |
| hd = hd_gu if proj != "down_proj" else hd_down[r] |
| pres.append((proj, r, encode_slice_prologue_pre( |
| sl, hd, slice_seed(L, E, pi, r), out_scales, logfile=None))) |
| g_scale_gss_lockstep([c for _, _, c in pres], None, self_check=False) |
| ctxs31 = [(proj, r, encode_slice_prologue_post(c)) for proj, r, c in pres] |
| walks = [LDLQWalk(c) for _, _, c in ctxs31 if c["wq_reg"] is None] |
| lockstep_ldlq(walks, lockstep_n, None) |
| v31_out = {} |
| for proj, r, ctx in ctxs31: |
| v31_out[(proj, r)] = encode_slice_epilogue(ctx) |
| torch.cuda.synchronize() |
| t_v31 += time.time() - t1 |
| free_H_data(hd_gu, *hd_down) |
| del walks, ctxs31, pres |
|
|
| |
| for pi, proj, r, sl in slices: |
| (o2, s2) = v2_out[(proj, r)] |
| (o3, s3) = v3_out[(proj, r)] |
| (o31, s31) = v31_out[(proj, r)] |
| eq_31_2 = all(o31[t].numpy().tobytes() == o2[t].numpy().tobytes() |
| for t in ("trellis", "suh", "svh")) |
| eq_31_3 = all(o31[t].numpy().tobytes() == o3[t].numpy().tobytes() |
| for t in ("trellis", "suh", "svh")) |
| g_eq = (s31["g_scale"] == s3["g_scale"] == s2["g_scale"]) |
| ok = eq_31_2 and eq_31_3 and g_eq |
| sha = hashlib.sha256(o31["trellis"].numpy().tobytes()).hexdigest()[:16] |
| total += 1 |
| passed += int(ok) |
| log(f"ORACLE layer {L} E{E} {proj}.rank{r} k={sl.shape[0]} n={sl.shape[1]}: " |
| f"{'BYTE-IDENTICAL v3.1==v3==v2' if ok else '*** MISMATCH ***'} " |
| f"[trellis sha256[:16]={sha}] " |
| f"g v2={s2['g_scale']:.6f} v3={s3['g_scale']:.6f} v3.1={s31['g_scale']:.6f} " |
| f"g-exact={g_eq} nmse v2={s2['nmse']:.9e} v3.1={s31['nmse']:.9e} " |
| f"proxy v2={s2['proxy_err']:.9e} v3.1={s31['proxy_err']:.9e}", olog) |
| del slices, v2_out, v3_out, v31_out, snap_gu, snap_down |
| torch.cuda.empty_cache() |
| verdict = "PASS" if passed == total else "FAIL" |
| log(f"ORACLE {verdict}: {passed}/{total} slices byte-identical v3.1==v3==v2 " |
| f"(trellis+suh+svh, g_scale exact-equal), both geometries + shared-H " |
| f"semantics; identical inputs took v2 sequential {t_v2:.1f}s vs v3 " |
| f"lockstep {t_v3:.1f}s vs v3.1 pooled-GSS {t_v31:.1f}s (contended timings)", olog) |
| if passed != total: |
| sys.exit(2) |
|
|
|
|
| def bench(args): |
| """Short v3 throughput probe (no --work writes): run --bench-experts |
| experts of one layer through the FULL v3 per-expert path (shard load + |
| H build + 12 prologues + lockstep LDLQ + epilogues incl. every exactness |
| assert) and report s/expert. Safe to run beside a live encode; timings |
| are then worst-case contended.""" |
| torch, _ = _lazy_torch() |
| layers = parse_layers(args.layers) |
| assert len(layers) == 1, "--bench expects exactly one layer, e.g. --layers 72" |
| L = layers[0] |
| check_capture(args.capture_dir, [L]) |
| lockstep_n = resolve_lockstep(args.lockstep) |
| out_scales = {"auto": None, "always": True, "never": False}[args.out_scales] |
| src = SourceModel(args.src) |
| log(f"BENCH start (v3.1 pooled GSS): layer {L}, {args.bench_experts} experts, " |
| f"lockstep={lockstep_n}, gpu {torch.cuda.get_device_name(0)}") |
| calib = LayerCalib(args.capture_dir, L, None) |
| device = "cuda:0" |
| group_size = max(1, (lockstep_n + 3 * TP - 1) // (3 * TP)) |
| times = [] |
| E0 = 0 |
| while E0 < args.bench_experts: |
| Es = list(range(E0, min(E0 + group_size, args.bench_experts))) |
| torch.cuda.synchronize() |
| te = time.time() |
| pre_list, walk_ctxs, group_hd = [], [], [] |
| for E in Es: |
| W = {proj: load_expert_bf16(src, L, E, proj, device, None) for proj in PROJS} |
| hd_gu, hd_down, _hm = build_expert_hessians( |
| calib, E, W["gate_proj"], W["up_proj"], device, args.min_routed) |
| for pi, proj in enumerate(PROJS): |
| for r, sl in expert_slices(W[proj], proj): |
| hd = hd_gu if proj != "down_proj" else hd_down[r] |
| pre_list.append(encode_slice_prologue_pre( |
| sl, hd, slice_seed(L, E, pi, r), out_scales)) |
| del W |
| group_hd.append((hd_gu, hd_down)) |
| tg = time.time() |
| g_scale_gss_lockstep(pre_list) |
| torch.cuda.synchronize() |
| tg = time.time() - tg |
| ordered = [] |
| for ctx in pre_list: |
| ctx = encode_slice_prologue_post(ctx) |
| ordered.append(ctx) |
| if ctx["wq_reg"] is None: |
| walk_ctxs.append(ctx) |
| walks = [LDLQWalk(c) for c in walk_ctxs] |
| tq = time.time() |
| lockstep_ldlq(walks, lockstep_n) |
| tq = time.time() - tq |
| for ctx in ordered: |
| encode_slice_epilogue(ctx) |
| ctx.clear() |
| for hd_gu, hd_down in group_hd: |
| free_H_data(hd_gu, *hd_down) |
| torch.cuda.synchronize() |
| dt = (time.time() - te) / len(Es) |
| times.append(dt) |
| log(f"BENCH experts {Es[0]}-{Es[-1]}: {dt:.2f}s/expert " |
| f"(lockstep main pass {tq/len(Es):.2f}s/expert, " |
| f"pooled gss {tg/len(Es):.2f}s/expert)") |
| E0 += group_size |
| times_sorted = sorted(times) |
| mean = sum(times) / len(times) |
| log(f"BENCH RESULT (v3.1 pooled GSS): layer {L}, {len(times)} pool(s), " |
| f"lockstep={lockstep_n} — mean {mean:.2f}s/expert, best {times_sorted[0]:.2f}, " |
| f"worst {times_sorted[-1]:.2f} " |
| f"(v3 baselines: 19.92s bench under 3-contention, ~5.1s solo in enc3)") |
| log(f"BENCH projection at --workers 4 (1/GPU): {mean:.1f}s/expert -> " |
| f"{mean*256/60:.1f} min/layer/worker -> {mean*256*75/4/3600:.1f} h for 75 layers") |
|
|
|
|
| |
| |
| |
|
|
| def main(): |
| ap = argparse.ArgumentParser(description="GLM-5.2 NVFP4 -> EXL3-tr3 hybrid encoder") |
| ap.add_argument("--encode", action="store_true", help="run multi-GPU encode (default action)") |
| ap.add_argument("--assemble", action="store_true", help="assemble final checkpoint dir") |
| ap.add_argument("--upload", action="store_true", help="upload --out to private HF repo") |
| ap.add_argument("--smoke", action="store_true", help="kernel/roundtrip smoke test on random data") |
| ap.add_argument("--src", default=DEF_SRC) |
| ap.add_argument("--work", default=DEF_WORK) |
| ap.add_argument("--out", default=DEF_OUT) |
| ap.add_argument("--repo", default=DEF_REPO) |
| ap.add_argument("--layers", default=f"{FIRST_MOE_LAYER}-{NUM_LAYERS-1}", |
| help="e.g. '3-77' or '3,5,10-12'") |
| ap.add_argument("--workers", type=int, default=4) |
| ap.add_argument("--gpus", type=int, default=4, |
| help="physical GPU count; workers are assigned round-robin (worker r -> GPU r%%gpus)") |
| ap.add_argument("--io-workers", type=int, default=12) |
| ap.add_argument("--capture-dir", default=DEF_CAPTURE, |
| help="Pass A output (capture_hessians.py) — REQUIRED for --encode") |
| ap.add_argument("--min-routed", type=int, default=MIN_ROUTED, |
| help="per-expert routed-token floor; below it the expert uses the " |
| "layer-level H (recorded in done JSON, never a failure)") |
| ap.add_argument("--out-scales", choices=["auto", "always", "never"], default="auto", |
| help="exl3 out-channel scales; 'auto' matches convert_model.py default " |
| "(calibrated: per-slice H-diag skew decision, reference math)") |
| ap.add_argument("--lockstep", default="auto", |
| help="v3: max LDLQ slice-walks co-stepped per quantize_tiles call; " |
| "'auto' = 12 (all walks of one expert); N>12 pools " |
| "ceil(N/12) experts per lockstep group") |
| ap.add_argument("--oracle", action="store_true", |
| help="HARD GATE: byte-equality of v2 sequential vs v3 lockstep vs " |
| "v3.1 pooled-GSS on real slices of ONE --layers layer; " |
| "logs to --oracle-log") |
| ap.add_argument("--oracle-experts", default="0,1", |
| help="comma-separated expert ids for --oracle (12 slices each)") |
| ap.add_argument("--oracle-log", default="/root/tr3_v31_oracle.log") |
| ap.add_argument("--bench", action="store_true", |
| help="v3 throughput probe on ONE --layers layer (no --work writes)") |
| ap.add_argument("--bench-experts", type=int, default=8) |
| ap.add_argument("--worker-rank", type=int, default=None, help=argparse.SUPPRESS) |
| args = ap.parse_args() |
|
|
| try: |
| if args.worker_rank is not None: |
| worker_main(args) |
| elif args.smoke: |
| smoke(args) |
| elif args.oracle: |
| oracle(args) |
| elif args.bench: |
| bench(args) |
| elif args.assemble: |
| assemble(args) |
| elif args.upload: |
| upload(args) |
| else: |
| orchestrate_encode(args) |
| except Exception: |
| traceback.print_exc() |
| sys.exit(1) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|