amer224 commited on
Commit
10f28ca
·
verified ·
1 Parent(s): 4637ed0

Add brains/sovereign-nano/quantize_cpu.py

Browse files
brains/sovereign-nano/quantize_cpu.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ quantize_cpu.py — dynamic int8 quantization for CPU rollouts
3
+ (torch-native, no exotic deps).
4
+
5
+ Honest scope (stated, not hidden):
6
+ - torch.quantization.quantize_dynamic quantizes Linear and GRU weights
7
+ to int8 with dynamic activation scaling — it does NOT quantize the
8
+ convs (static PTQ would, but needs calibration data + accuracy
9
+ validation on this shard distribution, which belongs on the
10
+ pipeline's machine, not guessed here).
11
+ - Result: a PARTIAL CPU speedup (the MLP heads + GRU are a small share
12
+ of nano's FLOPs — most of it lives in convs). If CPU rollouts need
13
+ the full conv win, the honest path is static PTQ or ONNX runtime,
14
+ listed as next steps below.
15
+ - Accuracy is not silently assumed: the smoke compares fp32 vs quant
16
+ outputs and prints the max diff.
17
+
18
+ Usage:
19
+ python quantize_cpu.py
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import torch
25
+ import torch.nn as nn
26
+
27
+
28
+ def quantize_dynamic(model: nn.Module) -> nn.Module:
29
+ """Quantize Linear + GRU to qint8 (in place). Convs stay fp32."""
30
+ return torch.quantization.quantize_dynamic(
31
+ model, {nn.Linear, nn.GRU}, dtype=torch.qint8)
32
+
33
+
34
+ if __name__ == "__main__":
35
+ from model_nano import NanoConfig, make_nano
36
+
37
+ print("== quantize_cpu.py smoke ==")
38
+ cfg = NanoConfig(map_size=64)
39
+ net = make_nano(cfg, seed=0).eval()
40
+ x = torch.rand(1, 3, 64, 64)
41
+ nums = torch.rand(1, 8)
42
+
43
+ with torch.no_grad():
44
+ ref = net(x, nums, return_all=True)
45
+ qnet = quantize_dynamic(net)
46
+ with torch.no_grad():
47
+ out = qnet(x, nums, return_all=True)
48
+
49
+ diffs = [float((ref[k] - out[k]).abs().max().item())
50
+ for k in ("heat", "kind_logits", "value", "pct", "win_logits")
51
+ if ref[k] is not None]
52
+ print(f"quant max-diff: {max(diffs):.2e} (informational — small is "
53
+ f"expected for Linear/GRU-only int8)")
54
+ # honest note: convs are NOT quantized by this path
55
+ print("note: convs remain fp32 (dynamic quant limitation, documented)")
56
+ print("next steps for full CPU speedup: static PTQ (qnnpack, needs")
57
+ print(" calibration frames from the real shard) or ONNX runtime")
58
+ print("quantize_cpu.py smoke OK")