75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
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") |