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 = {} 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 W = num(r"W\(n\):\s*([\d.]+)", block) key = (variant, n) if key not in best or cycles < best[key][2]: best[key] = (variant, n, cycles, n_iter, W, num(r"Q\(n\) per iteration:\s*([\d.]+)", block), num(r"I\(n\):\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, W, q, I = best[(variant, n)] fc = W / cycles w.writerow([variant, n, n_iter, W, q, I, round(cycles, 1), round(fc, 3)]) print("wrote", OUT, "with", len(best), "rows")