amer224 commited on
Commit
d712ccd
·
verified ·
1 Parent(s): fc3acb3

Add brains/sovereign-nano/bench.py

Browse files
Files changed (1) hide show
  1. brains/sovereign-nano/bench.py +139 -0
brains/sovereign-nano/bench.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ bench.py — measurable speed claims for SOVEREIGN-nano.
3
+
4
+ Every optimization in opt.py/model_nano gets a number here. The pipeline
5
+ can run this on CPU or 2xT4 and compare against nano_notes.md — if a
6
+ claim is off, this file is where it shows.
7
+
8
+ Usage:
9
+ python bench.py # CPU, default config
10
+ python bench.py --device cuda # T4
11
+ python bench.py --heat-res 64 # nuclear heat option
12
+ python bench.py --fp16 --device cuda # autocast (cuda only)
13
+ python bench.py --compile # torch.compile
14
+ python bench.py --channels-last # NHWC input path
15
+ python bench.py --batch 4 --iters 20
16
+
17
+ Runs forward + act and prints ms/frame and frames/sec for each config.
18
+ All runs are at map_size=256 (the real contract size) by default; use
19
+ --small 64 for a fast sanity path.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import argparse
25
+ import time
26
+
27
+ import torch
28
+
29
+ from model_nano import NanoConfig, make_nano
30
+
31
+
32
+ def timeit(fn, iters: int, warmup: int, device: torch.device) -> float:
33
+ for _ in range(warmup):
34
+ fn()
35
+ if device.type == "cuda":
36
+ torch.cuda.synchronize()
37
+ t0 = time.perf_counter()
38
+ for _ in range(iters):
39
+ fn()
40
+ if device.type == "cuda":
41
+ torch.cuda.synchronize()
42
+ return (time.perf_counter() - t0) / iters * 1e3
43
+
44
+
45
+ def run_one(cfg, device, args, label: str) -> None:
46
+ net = make_nano(cfg, seed=0).eval().to(device)
47
+ try:
48
+ from opt import fold_bn, to_channels_last
49
+ if args.fold:
50
+ fold_bn(net)
51
+ label += "+fold"
52
+ if args.compile:
53
+ from opt import compile_if_available
54
+ net = compile_if_available(net)
55
+ label += "+compile"
56
+ except ImportError:
57
+ pass
58
+
59
+ H = cfg.map_size
60
+ rgb = torch.rand(args.batch, 3, H, H, device=device)
61
+ nums = torch.rand(args.batch, 8, device=device)
62
+
63
+ def prep(x):
64
+ if args.channels_last and x.dim() == 4:
65
+ from opt import to_channels_last
66
+ return to_channels_last(x)
67
+ return x
68
+
69
+ ctx = None
70
+ if args.fp16 and device.type == "cuda":
71
+ ctx = torch.autocast(device_type="cuda", dtype=torch.float16)
72
+
73
+ def fwd():
74
+ if ctx is not None:
75
+ with ctx:
76
+ net(prep(rgb), nums)
77
+ else:
78
+ net(prep(rgb), nums)
79
+
80
+ def act():
81
+ if ctx is not None:
82
+ with ctx:
83
+ net.act(prep(rgb), nums)
84
+ else:
85
+ net.act(prep(rgb), nums)
86
+
87
+ try:
88
+ ms_fwd = timeit(fwd, args.iters, args.warmup, device)
89
+ ms_act = timeit(act, args.iters, args.warmup, device)
90
+ fps = 1000.0 / max(ms_act, 1e-6)
91
+ print(f"{label:38s} fwd {ms_fwd:7.2f} ms | act {ms_act:7.2f} ms "
92
+ f"| {fps:7.1f} acts/s")
93
+ except Exception as e:
94
+ print(f"{label:38s} FAILED: {str(e)[:120]} "
95
+ f"(config unsupported — stated, not hidden)")
96
+
97
+
98
+ def main() -> None:
99
+ ap = argparse.ArgumentParser()
100
+ ap.add_argument("--device", default="cpu")
101
+ ap.add_argument("--small", type=int, default=0,
102
+ help="use this map size instead of 256 (e.g. 64)")
103
+ ap.add_argument("--heat-res", type=int, default=0)
104
+ ap.add_argument("--batch", type=int, default=1)
105
+ ap.add_argument("--iters", type=int, default=10)
106
+ ap.add_argument("--warmup", type=int, default=3)
107
+ ap.add_argument("--fp16", action="store_true")
108
+ ap.add_argument("--compile", action="store_true")
109
+ ap.add_argument("--channels-last", action="store_true")
110
+ ap.add_argument("--fold", action="store_true")
111
+ args = ap.parse_args()
112
+
113
+ device = torch.device(args.device)
114
+ if device.type == "cuda" and not torch.cuda.is_available():
115
+ print("cuda requested but unavailable — falling back to CPU")
116
+ device = torch.device("cpu")
117
+ print(f"== SOVEREIGN-nano bench | device={device} batch={args.batch} "
118
+ f"iters={args.iters} ==")
119
+
120
+ size = args.small or 256
121
+ base = NanoConfig(map_size=size)
122
+ run_one(base, device, args, f"baseline {size}px")
123
+
124
+ if args.heat_res:
125
+ hr = NanoConfig(map_size=size, heat_res=args.heat_res)
126
+ run_one(hr, device, args, f"heat_res={args.heat_res}")
127
+ if args.fold:
128
+ run_one(base, device, args, "baseline")
129
+ if args.channels_last:
130
+ run_one(base, device, args, "baseline")
131
+ if args.compile:
132
+ run_one(base, device, args, "baseline")
133
+ if args.fp16:
134
+ run_one(base, device, args, "baseline")
135
+ print("done")
136
+
137
+
138
+ if __name__ == "__main__":
139
+ main()