sceneseg-p150 / code /scripts /diag /slice_probe.py
changh95's picture
tt-model push sceneseg-p150 (container)
e0adbab verified
Raw History Blame Contribute Delete
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())