File size: 4,577 Bytes
4a3e194 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | """The cost of instantiation against the cost of the network.
One generation of the host is: inst splits the emitted bytes, sigma^-1 parses
the first field into the netlist, Lev places the rows and entries of the
layered map, and the device is applied once per step. This script counts those
operations, one per byte read by inst and by sigma^-1, one per row and one per
nonzero entry placed by Lev, and one per device application, times each of
them, and compares the total with the T * M unit evaluations of the run.
"""
import json
import os
import sys
import time
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def runs_path(name: str) -> str:
d = os.path.join(REPO, "paper", "runs")
os.makedirs(d, exist_ok=True)
return os.path.join(d, name)
def main() -> int:
from selfrep import (M_STAR, inst, ser, tau_star, run_reference, read_host,
host_netlist, sigma_host)
from netlist_io import net_of_sigma
from matrix8 import compile_net
sigma_bytes = read_host()
tau = tau_star(sigma_bytes, M_STAR)
s = ser(sigma_bytes, bytes(M_STAR), tau)
# sigma: parameters and predecessor entries stored, and the time to write
t0 = time.perf_counter()
net, inputs, outputs = host_netlist()
t_build = time.perf_counter() - t0
t0 = time.perf_counter()
encoded = sigma_host()
t_sigma = time.perf_counter() - t0
assert encoded == sigma_bytes
stored, _, _, _ = net_of_sigma(sigma_bytes)
entries = (2 * len(stored.gates) # bias and fan-in
+ sum(len(i) for i, _ in stored.gates.values())
+ len(outputs))
print(f" sigma: {entries:,} stored entries -> {len(encoded):,} bytes "
f"in {t_sigma * 1e3:.0f} ms ({t_build * 1e3:.0f} ms to assemble "
f"the netlist from source)")
# inst: one pass over the serialized instance, then sigma^-1 on its first field
t0 = time.perf_counter()
reps = 50
for _ in range(reps):
a, b, c = inst(s)
t_inst = (time.perf_counter() - t0) / reps
assert (a, b, c) == (sigma_bytes, bytes(M_STAR), tau)
t0 = time.perf_counter()
for _ in range(5):
N, I, O, _ = net_of_sigma(a)
t_sigma_inv = (time.perf_counter() - t0) / 5
assert len(N.gates) == len(stored.gates)
print(f" inst: {len(s):,} bytes parsed in {t_inst * 1e3:.2f} ms, and "
f"{len(N.gates):,} units rebuilt from the first field in "
f"{t_sigma_inv * 1e3:.0f} ms")
# Lev: the units placed, and the time to place them
t0 = time.perf_counter()
layers, info = compile_net(N, I, O)
t_lev = time.perf_counter() - t0
M = sum(int(W.shape[0]) for W, _ in layers)
nnz = sum(int((W != 0).sum()) for W, _ in layers)
print(f" Lev: {len(N.gates):,} units in, {M:,} rows and {nnz:,} nonzero "
f"entries placed over {info['layers']} layers in {t_lev:.1f} s")
# the device: one application per step, at most one byte moved
t0 = time.perf_counter()
emitted, T = run_reference(M_STAR, tau)
t_run = time.perf_counter() - t0
assert emitted == s
print(f" device: {T:,} applications, {len(emitted):,} bytes emitted "
f"({t_run:.2f} s for the whole reference run)")
env_ops = len(s) + len(sigma_bytes) + M + nnz + T
closed = 2 * len(sigma_bytes) + len(bytes(M_STAR)) + len(tau) + 16 + M + nnz + T
assert env_ops == closed, (env_ops, closed)
net_ops = T * M
print(f" instantiation: {env_ops:,} elementary operations per generation, "
f"which is the closed form 2|sigma|+|m|+|tau|+16+M+nnz+T")
print(f" network: {net_ops:,} unit evaluations (T = {T:,}, M = {M:,})")
print(f" ratio: {env_ops / net_ops:.3e}")
out = {"sigma_entries": entries, "sigma_bytes": len(encoded),
"sigma_seconds": t_sigma, "build_seconds": t_build,
"inst_bytes": len(s), "inst_seconds": t_inst,
"sigma_inverse_seconds": t_sigma_inv,
"lev_units_in": len(N.gates), "lev_units_out": M, "lev_nonzero": nnz,
"lev_layers": info["layers"], "lev_seconds": t_lev,
"lev_entries": info["total_weights"],
"steps": T, "emitted_bytes": len(emitted),
"reference_seconds": t_run,
"environment_ops": env_ops, "network_ops": net_ops,
"ratio": env_ops / net_ops}
json.dump(out, open(runs_path("paper_environment.json"), "w"), indent=1)
return 0
if __name__ == "__main__":
sys.exit(main())
|