Download code/scripts/micro/bcast_test.py from changh95/hamer-p150: direct link, hf CLI and curl.
- Browser
- Download file 5.73 kB
-
https://huggingface.co/changh95/hamer-p150/resolve/main/code/scripts/micro/bcast_test.py
- Command line
-
hf download hf://changh95/hamer-p150/code/scripts/micro/bcast_test.py
-
curl -L -o bcast_test.py https://huggingface.co/changh95/hamer-p150/resolve/main/code/scripts/micro/bcast_test.py
5.73 kB
| """Two-hop activation broadcast (kernels/mcbench/bcast2.cpp), round 7. | |
| usage: bcast_test.py mode=rc|cr [cols=12] [rows=10] [sb=49152] [noc=0|1] [verify=1] [time=1] [nodata=0] | |
| rc: shard r starts at (0, r); hop A = row multicast, hop B = chain of column multicasts (12 columns in parallel) | |
| cr: shard c starts at (c, 0) (c < NSH); hop A = column multicast, hop B = chain of row multicasts (rows in parallel)""" | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[2])) | |
| from common import * | |
| K = str(Path(__file__).resolve().parents[2] / "hamer/kernels/mcbench/bcast2.cpp") | |
| args = dict(a.split("=") for a in sys.argv[1:]) | |
| mode = args.get("mode", "rc") | |
| C, R = int(args.get("cols", 12)), int(args.get("rows", 10)) | |
| SB = int(args.get("sb", 49152)) | |
| noc = int(args.get("noc", 0)) | |
| verify = args.get("verify", "1") == "1" | |
| NSH = R if mode == "rc" else int(args.get("nsh", 10)) | |
| assert NSH <= 14 | |
| dev = open_dev() | |
| try: | |
| phys = {(x, y): dev.worker_core_from_logical_core(ttnn.CoreCoord(x, y)) for x in range(C) for y in range(R)} | |
| cores = ttnn.CoreRangeSet([ttnn.CoreRange(ttnn.CoreCoord(0, 0), ttnn.CoreCoord(C - 1, R - 1))]) | |
| def rect(x0, y0, x1, y1): | |
| p0, p1 = phys[(x0, y0)], phys[(x1, y1)] | |
| return [min(p0.x, p1.x), min(p0.y, p1.y), max(p0.x, p1.x), max(p0.y, p1.y)] | |
| out = ttnn.from_torch(torch.zeros(C * R, 8, dtype=torch.int32), dtype=ttnn.uint32, layout=ttnn.ROW_MAJOR_LAYOUT, | |
| device=dev, memory_config=ttnn.DRAM_MEMORY_CONFIG) | |
| def build(empty=False): | |
| rt = ttnn.RuntimeArgs() | |
| for x in range(C): | |
| for y in range(R): | |
| a = [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, SB, out.buffer_address(), | |
| y * C + x] | |
| if not empty: | |
| if mode == "rc": | |
| # hop A: row y, head (0, y) holds shard y; hop B: column x, chain y = 0..R-1 | |
| p = phys[(0, y)] | |
| a[0] = y | |
| a[1] = 1 if x == 0 else 0 | |
| a[2:6] = rect(0, y, C - 1, y); a[6] = C | |
| a[7:11] = rect(x, 0, x, R - 1); a[11] = R | |
| a[12] = y; a[13] = y - 1 if y else 0 | |
| a[14] = 0 if x == 0 else 1; a[15:17] = [p.x, p.y] | |
| q = phys[(x, 0)] | |
| a[17] = 0 if y == 0 else 1; a[18:20] = [q.x, q.y]; a[20] = 1 if y == 0 else 0 | |
| else: | |
| # hop A: column x (x < NSH), head (x, 0) holds shard x; hop B: row y, chain x = 0..NSH-1 | |
| if x < NSH: | |
| p = phys[(x, 0)] | |
| a[0] = x | |
| a[1] = 1 if y == 0 else 0 | |
| a[2:6] = rect(x, 0, x, R - 1); a[6] = R | |
| a[12] = x; a[13] = x - 1 if x else 0 | |
| a[14] = 0 if y == 0 else 1; a[15:17] = [p.x, p.y] | |
| a[7:11] = rect(0, y, C - 1, y); a[11] = C | |
| q = phys[(0, y)] | |
| a[17] = 0 if x == 0 else 1; a[18:20] = [q.x, q.y]; a[20] = 1 if x == 0 else 0 | |
| a[21] = NSH | |
| rt[x][y] = a | |
| cfg = ttnn.ReaderConfigDescriptor() if noc == 0 else ttnn.WriterConfigDescriptor() | |
| defs = ([("BC_VERIFY", "1")] if verify else []) + ([("BC_NO_DATA", "1")] if args.get("nodata") == "1" else []) \ | |
| + [(d, "1") for d in filter(None, args.get("defs", "").split(","))] | |
| kd = ttnn.KernelDescriptor(kernel_source=K, source_type=ttnn.KernelDescriptor.SourceType.FILE_PATH, core_ranges=cores, | |
| compile_time_args=list(ttnn.TensorAccessorArgs(out).get_compile_time_args()), | |
| defines=defs, runtime_args=rt, config=cfg) | |
| cbs = [ttnn.CBDescriptor(total_size=NSH * SB if not empty else 2048, core_ranges=cores, format_descriptors=[ | |
| ttnn.CBFormatDescriptor(buffer_index=0, data_format=ttnn.bfloat16, page_size=2048)]), | |
| ttnn.CBDescriptor(total_size=256, core_ranges=cores, format_descriptors=[ | |
| ttnn.CBFormatDescriptor(buffer_index=1, data_format=ttnn.uint32, page_size=256)])] | |
| sems = [ttnn.SemaphoreDescriptor(id=i, core_ranges=cores, initial_value=0) for i in range(2 + NSH)] | |
| return ttnn.ProgramDescriptor(kernels=[kd], semaphores=sems, cbs=cbs) | |
| prog = build() | |
| ttnn.generic_op([out, out], prog) | |
| ttnn.synchronize_device(dev) | |
| if verify: | |
| r = ttnn.to_torch(out).reshape(C * R, 8) | |
| bad = int(r[:, 0].sum()); tags = int(((r[:, 1].to(torch.int64) & 0xFFFF0000) == 0xC0DE0000).sum()) | |
| print(f"[bc] {mode} verify: cores reporting {tags}/{C*R}, mismatched words {bad}", flush=True) | |
| if args.get("prof") == "1": | |
| pe = build(empty=True) | |
| prof_run(dev, "empty", lambda: (ttnn.generic_op([out, out], pe), None)[1]) | |
| prof_run(dev, "bcast", lambda: (ttnn.generic_op([out, out], prog), None)[1]) | |
| if args.get("time", "1") == "1": | |
| reps = int(args.get("reps", 20)) | |
| pe = build(empty=True) | |
| te = time_op(dev, lambda: (ttnn.generic_op([out, out], pe), None)[1], reps=reps) | |
| tb = time_op(dev, lambda: (ttnn.generic_op([out, out], prog), None)[1], reps=reps) | |
| tot = NSH * SB | |
| print(f"[bc] {mode} noc{noc} {C}x{R} NSH={NSH} SB={SB}: empty {te:.2f} us, bcast {tb:.2f} us -> {tb - te:.2f} us" | |
| f" ({tot / max(tb - te, 1e-3) / 1e3:.1f} GB/s per receiver)", flush=True) | |
| finally: | |
| from open_device_12x10 import close_device | |
| close_device(dev) | |
| if args.get("prof") == "1": | |
| prof_report() | |