jon1012 commited on
Commit
1abd948
·
verified ·
1 Parent(s): 92fcf87

Sync verify_transcode.py (streamed Engram + GPU option, verifier, synthetic engram test)

Browse files
Files changed (1) hide show
  1. verify_transcode.py +80 -0
verify_transcode.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Prove the MXFP4->NVFP4 expert transcode is bit-exact, and measure the Engram FP4 loss.
3
+
4
+ Reconstructs values from BOTH representations and compares:
5
+ source : FP4_TABLE[nibble] * scale_e8m0
6
+ output : FP4_TABLE[nibble] * scale_e4m3 * global_f32
7
+ A single non-identical element fails the run.
8
+ """
9
+ import json, os, sys
10
+ import torch
11
+ from safetensors import safe_open
12
+
13
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
14
+ from dsv41_fp4_stream import (FP4_TABLE, SRC_BLOCK, NVFP4_BLOCK, EXPERT_RE, ENGRAM_RE,
15
+ unpack_e2m1)
16
+
17
+ src_dir, out_dir, shard = sys.argv[1], sys.argv[2], sys.argv[3]
18
+
19
+ sf = safe_open(os.path.join(src_dir, shard), framework="pt")
20
+ of = safe_open(os.path.join(out_dir, shard), framework="pt")
21
+ src_keys, out_keys = set(sf.keys()), set(of.keys())
22
+
23
+ n_exp = n_bad = 0
24
+ max_abs = 0.0
25
+ checked_elems = 0
26
+ for name in sorted(src_keys):
27
+ if not EXPERT_RE.match(name):
28
+ continue
29
+ base = name[:-len(".weight")]
30
+ a = unpack_e2m1(sf.get_tensor(name))
31
+ sa = sf.get_tensor(base + ".scale").float()
32
+ ref = a.view(a.shape[0], -1, SRC_BLOCK) * sa.unsqueeze(-1)
33
+ ref = ref.reshape(a.shape)
34
+
35
+ b = unpack_e2m1(of.get_tensor(base + ".weight"))
36
+ sb = of.get_tensor(base + ".weight_scale").float()
37
+ g = of.get_tensor(base + ".weight_scale_2").float()
38
+ got = b.view(b.shape[0], -1, NVFP4_BLOCK) * (sb * g).unsqueeze(-1)
39
+ got = got.reshape(b.shape)
40
+
41
+ d = (ref - got).abs().max().item()
42
+ max_abs = max(max_abs, d)
43
+ if d != 0.0:
44
+ n_bad += 1
45
+ if n_bad <= 3:
46
+ print(f" MISMATCH {base} max|d|={d:.6g}")
47
+ n_exp += 1
48
+ checked_elems += ref.numel()
49
+ if n_exp >= 200: # 200 experts is plenty and keeps the check quick
50
+ break
51
+
52
+ print(f"[experts] {n_exp} weights checked ({checked_elems/1e6:.1f}M elements), "
53
+ f"mismatches={n_bad}, max|delta|={max_abs:.6g}")
54
+
55
+ n_eng = 0
56
+ for name in sorted(src_keys):
57
+ if not ENGRAM_RE.match(name):
58
+ continue
59
+ base = name[:-len(".weight")]
60
+ rows = 65536
61
+ w = sf.get_slice(name)[:rows]
62
+ s = sf.get_slice(base + ".scale")[:rows].float()
63
+ ref = w.float().view(rows, -1, SRC_BLOCK) * s.unsqueeze(-1)
64
+
65
+ b = unpack_e2m1(of.get_slice(base + ".weight")[:rows])
66
+ sb = of.get_slice(base + ".scale")[:rows].float()
67
+ got = b.view(rows, -1, SRC_BLOCK) * sb.unsqueeze(-1)
68
+
69
+ a2, b2 = ref.flatten(1), got.flatten(1)
70
+ num = (a2 * b2).sum(1); den = a2.norm(dim=1) * b2.norm(dim=1)
71
+ ok = den > 0
72
+ cos = (num[ok] / den[ok])
73
+ rel = ((a2 - b2).norm(dim=1) / a2.norm(dim=1).clamp(min=1e-30))[ok]
74
+ print(f"[engram] {base} rows={rows} cos mean={cos.mean():.6f} min={cos.min():.6f} "
75
+ f"rel-err mean={rel.mean():.4f}")
76
+ n_eng += 1
77
+
78
+ if n_eng == 0:
79
+ print("[engram] none in this shard")
80
+ print("RESULT:", "LOSSLESS" if n_bad == 0 and n_exp > 0 else ("FAIL" if n_bad else "no experts here"))