sceneseg-p150 / code /scripts /diag /ss_precision_emulation.py
changh95's picture
tt-model push sceneseg-p150 (container)
aec3f16 verified
Raw History Blame Contribute Delete
4.66 kB
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""CPU emulation of the TT graph's numerics (no device): the real ``tt_sceneseg.tt`` graph executed by the fake ttnn
of ``common/tests/host`` (bf16-rounded operands and outputs, float64 products and sums), one and two weight terms, on
a few frames, against the fp32 CPU reference goldens: class-map agreement, foreground IoU, logits PCC. The evidence
behind the weight-terms default (PORT_LOG.md M1), next to the device runs.
source bin/tt-env.sh; cd bundles/sceneseg-p150
PYTHONPATH=$PWD/code:$PYTHONPATH TT_VISIBLE_DEVICES=none OMP_NUM_THREADS=4 python code/scripts/diag/ss_precision_emulation.py \
--frames tut_highway_rain_2,ps019_f40_front_camera --terms 1,2 --json ../../logs/sceneseg/m1_precision_emulation.json
"""
from __future__ import annotations
import argparse
import importlib.util
import json
import sys
import time
from pathlib import Path
import numpy as np
BUNDLE = Path(__file__).resolve().parents[3]
WS = BUNDLE.parents[1]
sys.path.insert(0, str(BUNDLE / "code"))
def install_fake():
"""The fake ttnn (+ its CNN ops and a row sum) as ``ttnn``; never the real one."""
host = WS / "common" / "tests" / "host"
spec = importlib.util.spec_from_file_location("fake_ttnn", host / "fake_ttnn.py")
fake = importlib.util.module_from_spec(spec)
sys.modules["fake_ttnn"] = fake
spec.loader.exec_module(fake)
ttnn = fake.install()
spec = importlib.util.spec_from_file_location("fake_ttnn_cnn", host / "fake_ttnn_cnn.py")
cnn = importlib.util.module_from_spec(spec)
sys.modules["fake_ttnn_cnn"] = cnn
spec.loader.exec_module(cnn)
cnn.install(ttnn)
def sum_(t, dim=None, keepdim=False, **_):
return ttnn._op("sum", [t], lambda x: x.sum(axis=dim, keepdims=keepdim), t.dtype, t.layout, (dim, keepdim))
ttnn.sum = sum_
return ttnn
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
ap.add_argument("--frames", default="tut_highway_rain_2,ps019_f40_front_camera")
ap.add_argument("--terms", default="1,2")
ap.add_argument("--order", default="bgr")
ap.add_argument("--json", default="")
a = ap.parse_args()
ttnn = install_fake()
if not hasattr(ttnn, "subtract"): # the activation term split (tt/layers.split_activation)
ttnn.subtract = lambda x, y, **_: ttnn._op("subtract", [x, y], lambda u, v: u - v, x.dtype, x.layout)
import torch
torch.set_num_threads(4)
from tt_sceneseg.host.preprocess import prepare_bgr
from tt_sceneseg.reference import assets
from tt_sceneseg.reference.weights import load_weights
from tt_sceneseg.tests import sceneseg_eval as ev
from tt_sceneseg.tt.model import TtSceneSeg
from tt_sceneseg.ttaw.device import open_device
from tt_sceneseg.ttaw.metrics import pcc
dev = open_device(0, dispatch="eth", num_command_queues=1)
weights = load_weights(assets.onnx_path())
gold = WS / "research" / "sceneseg" / "goldens" / "public"
inputs = WS / "research" / "sceneseg" / "public_data" / "inputs"
results = {}
for terms in (int(t) for t in a.terms.split(",")):
model = TtSceneSeg(weights, a.order, weight_terms=terms)
for fid in a.frames.split(","):
t0 = time.perf_counter()
bgr = np.ascontiguousarray(ev.load_rgb(inputs / fid / "source_bgr.png")[:, :, ::-1])
canvas = prepare_bgr(bgr, channel_order=a.order).device_input()
image = ttnn.from_torch(torch.from_numpy(canvas), dtype=ttnn.uint8, layout=ttnn.ROW_MAJOR_LAYOUT,
device=dev)
out = model.forward(image, logits=True)
cmap = ttnn.to_torch(out["class_map"]).numpy().reshape(320, 640)
logits = ttnn.to_torch(out["logits"]).float().numpy()
with np.load(gold / f"{fid}.npz") as z:
ref_logits, ref_cls = z[f"logits_{a.order}"], z[f"cls_{a.order}"]
rec = {"logits_pcc": pcc(logits, ref_logits), "agreement": ev.argmax_agreement(cmap, ref_cls),
"foreground_iou": ev.foreground_iou(cmap, ref_cls),
"fg_fraction": float((cmap == 1).mean()), "fg_fraction_fp32": float((ref_cls == 1).mean()),
"seconds": round(time.perf_counter() - t0, 1)}
results[f"terms{terms}/{fid}"] = rec
print(f"terms={terms} {fid}: {json.dumps(rec)}", flush=True)
model.release()
if a.json:
Path(a.json).write_text(json.dumps({"order": a.order, "results": results}, indent=1) + "\n")
return 0
if __name__ == "__main__":
sys.exit(main())