import os import re import csv # folder that holds one subfolder per variant, each with an x86/ dir full of *.log files ROOT = "measurements" OUT = "analysis/results.csv" # the benchmark prints one block per problem size, looks like: # === N_P=500 N_ITER=200 === # W(n) per iteration: ... # Q(n) per iteration: ... # I(n): ... # W(n): ... # T(n): ... <- cycles # P(n): ... <- flops/cycle # so I split each log on the "=== N_P=.. ===" lines and read the fields out of each block. size_line = re.compile(r"=== N_P=(\d+) N_ITER=(\d+) ===") def num(pattern, text): m = re.search(pattern, text) if m: return float(m.group(1)) return None #we run every variant a few times (1.log, 2.log, ...). keep the fastest run per size, #min cycles is the standard way to kill the OS/turbo noise. best = {} # flop counter is uint32 and wraps at n=10000 (72*n^2+74*n = 7.2e9 > 2^32), so the logged # W(n)/I(n) are garbage there. compute work ourselves; matches the good logs exactly. # symmetry variants do half the pairs -> 36 n^2 + 110 n, everything else 72 n^2 + 74 n. def flops_per_iter(variant, n): if "symmetry" in variant: return 36 * n * n + 110 * n return 72 * n * n + 74 * n for variant in sorted(os.listdir(ROOT)): logdir = os.path.join(ROOT, variant, "x86") if not os.path.isdir(logdir): continue for fn in os.listdir(logdir): if not fn.endswith(".log"): continue text = open(os.path.join(logdir, fn)).read() marks = list(size_line.finditer(text)) for i, m in enumerate(marks): n = int(m.group(1)) n_iter = int(m.group(2)) start = m.end() stop = marks[i + 1].start() if i + 1 < len(marks) else len(text) block = text[start:stop] cycles = num(r"T\(n\):\s*([\d.]+)", block) if cycles is None: continue key = (variant, n) if key not in best or cycles < best[key][0]: best[key] = (cycles, n_iter, num(r"Q\(n\) per iteration:\s*([\d.]+)", block)) with open(OUT, "w", newline="") as f: w = csv.writer(f) w.writerow(["variant", "n", "n_iter", "W", "Q_per_iter", "I", "cycles", "flops_per_cycle"]) for variant, n in sorted(best): cycles, n_iter, q = best[(variant, n)] w_iter = flops_per_iter(variant, n) W = w_iter * n_iter I = w_iter / q fc = W / cycles w.writerow([variant, n, n_iter, W, q, round(I, 2), round(cycles, 1), round(fc, 3)]) print("wrote", OUT, "with", len(best), "rows")