Download code/scripts/diag/slice_probe.py from changh95/sceneseg-p150: direct link, hf CLI and curl.
- Browser
- Download file 6.02 kB
-
https://huggingface.co/changh95/sceneseg-p150/resolve/main/code/scripts/diag/slice_probe.py
- Command line
-
hf download hf://changh95/sceneseg-p150/code/scripts/diag/slice_probe.py
-
curl -L -o slice_probe.py https://huggingface.co/changh95/sceneseg-p150/resolve/main/code/scripts/diag/slice_probe.py
6.02 kB
| #!/usr/bin/env python3 | |
| # SPDX-License-Identifier: Apache-2.0 | |
| """Round-6 probe (OPT_PLAN status after round 5, item 2): ttnn's DRAM-sliced decoder convs under explicit slice / | |
| Conv2dConfig choices. Each decoder kxk conv that runs the DRAM-sliced path in the served graph (bf16 DRAM input, one | |
| bf16 weight term, fp32 output, the decoder fidelity) is timed in a trace (10 calls, 5 replays) per configuration and | |
| its output compared bit for bit with the automatic configuration. | |
| bin/devrun -t 1500 -- python -u code/scripts/diag/slice_probe.py [--only dl5,z4] [--cfg auto,h2,...] | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import sys | |
| import time | |
| import numpy as np | |
| # name -> (H, W, Cin, Cout, k): the served graph's DRAM-sliced convs (input map size) | |
| SHAPES = {"dl5": (80, 160, 512, 256, 3), "z4": (160, 320, 128, 512, 3), "dl7": (160, 320, 256, 128, 3), | |
| "dl9": (320, 640, 128, 64, 3), "mrg": (320, 640, 64, 32, 3), | |
| # L1-path convs (CONV_L1 = 3200 px): second 3x3s of blocks 0-1, S1 Z convs (k3 forms) of blocks 0-2, | |
| # block 3's Z phases (80x160, DRAM-sliced) | |
| "dl1": (20, 40, 768, 768, 3), "dl3": (40, 80, 512, 512, 3), "z0": (10, 20, 1280, 3072, 2), | |
| "z1": (20, 40, 768, 2048, 2), "z2": (40, 80, 512, 2048, 2), "z3p": (80, 160, 256, 256, 2), | |
| # backbone 1x1 convs (matmul path; stacked [W_hi ; W_lo] outputs): expand of stages 2 / 3 / 4 / 6, | |
| # project of stages 2 / 3 | |
| "ex2": (160, 320, 16, 192, 1), "ex3": (80, 160, 24, 288, 1), "ex4": (40, 80, 40, 480, 1), | |
| "ex6": (20, 40, 112, 1344, 1), "pr2": (80, 160, 96, 64, 1), "pr3": (40, 80, 144, 64, 1)} | |
| def _configs(): | |
| import ttnn | |
| hs, bs = ttnn.TensorMemoryLayout.HEIGHT_SHARDED, ttnn.TensorMemoryLayout.BLOCK_SHARDED | |
| db = {"enable_act_double_buffer": True, "enable_weights_double_buffer": True} | |
| c = {"auto": ("auto", {}), "db": ("auto", db)} | |
| for n in (2, 3, 4, 6, 8): | |
| c[f"h{n}"] = (("height", n), {}) | |
| c[f"h{n}db"] = (("height", n), db) | |
| for n in (2, 4, 8): | |
| c[f"w{n}"] = (("width", n), {}) | |
| c["l1"] = ("l1", {}) | |
| c["l1db"] = ("l1", db) | |
| c["l1adb"] = ("l1", {"enable_act_double_buffer": True}) | |
| c["l1wdb"] = ("l1", {"enable_weights_double_buffer": True}) | |
| c["adb"] = ("auto", {"enable_act_double_buffer": True}) | |
| c["wdb"] = ("auto", {"enable_weights_double_buffer": True}) | |
| for n in (2, 4): | |
| c[f"h{n}hs"] = (("height", n), {"shard_layout": hs}) | |
| c[f"h{n}bs"] = (("height", n), {"shard_layout": bs}) | |
| for a in (64, 128, 256): | |
| c[f"h{n}a{a}"] = (("height", n), {"act_block_h_override": a}) | |
| c["hs"] = ("auto", {"shard_layout": hs}) | |
| c["bs"] = ("auto", {"shard_layout": bs}) | |
| c["fid"] = ("auto", {"full_inner_dim": True}) | |
| return c | |
| def main() -> int: | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--only", default="") | |
| ap.add_argument("--cfg", default="") | |
| ap.add_argument("--fid", default="HiFi3") | |
| a = ap.parse_args() | |
| import torch | |
| import ttnn | |
| from tt_sceneseg.device import close_device, open_device | |
| from tt_sceneseg.tt.layers import _BiasFreeConv2d | |
| from tt_sceneseg.ttaw.ops.conv import CONV_PRECISION, FeatureMap | |
| from tt_sceneseg.ttaw.precision import Precision | |
| from tt_sceneseg.ttaw.tensors import round_to_bf16, to_numpy | |
| prec = Precision.parse(CONV_PRECISION).with_(fidelity=a.fid) | |
| dev = open_device() | |
| cfgs = _configs() | |
| want = [c for c in a.cfg.split(",") if c] or list(cfgs) | |
| base = "l1" if want[0].startswith("l1") else "auto" | |
| if base not in want: | |
| want = [base] + want | |
| rng = np.random.default_rng(6) | |
| for name, (H, W, ci, co, k) in SHAPES.items(): | |
| if a.only and name not in a.only.split(","): | |
| continue | |
| w = round_to_bf16((rng.standard_normal((co, ci, k, k)) / np.sqrt(ci * k * k)).astype(np.float32)) | |
| x = round_to_bf16(rng.standard_normal((H * W, ci)).astype(np.float32)).reshape(1, 1, H * W, ci) | |
| xt = ttnn.from_torch(torch.from_numpy(x), dtype=ttnn.bfloat16, layout=ttnn.TILE_LAYOUT, device=dev, | |
| memory_config=ttnn.DRAM_MEMORY_CONFIG) | |
| fm = FeatureMap(xt, 1, H, W, ci) | |
| ref = None | |
| for cname in want: | |
| slicing, cc = cfgs[cname] | |
| conv = _BiasFreeConv2d(w, None, padding=k // 2, precision=prec, output_dtype="float32", | |
| conv_config=cc, name=f"{name}.{cname}") | |
| conv.slicing = slicing | |
| try: | |
| y = conv(fm).tensor | |
| v = to_numpy(y).reshape(-1, y.shape[-1])[:H * W, :co].copy() | |
| ttnn.deallocate(y) | |
| if ref is None: | |
| ref = v | |
| same = "IDENTICAL" if np.array_equal(v.view(np.uint32), ref.view(np.uint32)) else \ | |
| f"DIFF max {float(np.abs(v - ref).max() / np.abs(ref).max()):.2e}" | |
| tid = ttnn.begin_trace_capture(dev, cq_id=0) | |
| for _ in range(10): | |
| ttnn.deallocate(conv(fm).tensor) | |
| ttnn.end_trace_capture(dev, tid, cq_id=0) | |
| ttnn.execute_trace(dev, tid, cq_id=0, blocking=True) | |
| t1 = time.perf_counter() | |
| for _ in range(5): | |
| ttnn.execute_trace(dev, tid, cq_id=0, blocking=False) | |
| ttnn.synchronize_device(dev) | |
| us = (time.perf_counter() - t1) / 50 * 1e6 | |
| ttnn.release_trace(dev, tid) | |
| print(f"{name} {H}x{W} {ci}->{co} {cname:8s} {us:9.1f} us {same}", flush=True) | |
| except Exception as e: # noqa: BLE001 (a rejected configuration is a result) | |
| msg = str(e).strip().splitlines() | |
| print(f"{name} {H}x{W} {ci}->{co} {cname:8s} FAILED {msg[0][:160] if msg else type(e).__name__}", | |
| flush=True) | |
| conv.release() | |
| ttnn.deallocate(xt) | |
| close_device(dev) | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |