hardware-counters
lscpu_test.py
"""
If you knew the target machine's lscpu output, could you predict?
The honest answer depends on whether the machine descriptors can be
IDENTIFIED, which needs variation across machines. With two machines every
static spec is a single binary contrast, so any "model" that uses them is
really fitting one number per feature: the ARCHER2-to-Cirrus difference. That
is indistinguishable from fitting a single global speedup constant, and it
cannot extrapolate to a third machine.
This quantifies the ceiling: how well could you POSSIBLY do with perfect
knowledge of the per-machine speedup, versus what lscpu-style specs give you.
"""
import os
import numpy as np, pandas as pd
D = os.environ.get("DISS_ROOT", "/work/project/project/user")
KEYS = ["app", "size", "ncore", "nthread"]
def merge(path):
df = pd.read_csv(path)
df = df[df.runtime_s > 0]
return df.groupby(KEYS, as_index=False).agg(
runtime_s=("runtime_s", "median"),
cyc=("PAPI_TOT_CYC", "median"),
ins=("PAPI_TOT_INS", "median"))
A = merge(f"{D}/data/runs_expanded.csv")
C = merge(f"{D}/data/cirrus_persets.csv")
m = pd.merge(A, C, on=KEYS, suffixes=("_a2", "_cir")).dropna()
m["speedup"] = m.runtime_s_a2 / m.runtime_s_cir
print(f"matched configurations: {len(m)}\n")
# what lscpu would tell you
CLOCK = 3.71 / 2.25 # peak clock ratio
CORES = 288 / 128 # cores per node ratio
print("what lscpu-style specs predict:")
print(f" peak clock ratio {CLOCK:.3f}")
print(f" cores/node ratio {CORES:.3f}\n")
print("what actually happened, per application:")
g = m.groupby("app").speedup.agg(["median", "min", "max", "count"])
print(g.round(3).to_string())
print(f"\n overall median speedup {m.speedup.median():.3f}")
print(f" spread: {m.speedup.min():.2f}x to {m.speedup.max():.2f}x "
f"({m.speedup.max()/m.speedup.min():.1f}x range)")
fac = lambda p, a: np.maximum(np.clip(p,1e-9,None)/a, a/np.clip(p,1e-9,None))
y = m.runtime_s_cir.values
t_a2 = m.runtime_s_a2.values
print("\nerror in predicting Cirrus runtime from the ARCHER2 runtime:")
rows = [
("no adjustment (t_cir = t_a2)", t_a2),
("lscpu: divide by clock ratio", t_a2 / CLOCK),
("lscpu: divide by clock x cores ratio", t_a2 / (CLOCK * CORES)),
("ONE fitted global speedup (needs runs)", t_a2 / m.speedup.median()),
]
for name, pred in rows:
e = fac(pred, y)
print(f" {name:42s} median {np.median(e):.3f}")
# the ceiling: perfect per-application knowledge
per_app = m.groupby("app").speedup.transform("median").values
e = fac(t_a2 / per_app, y)
print(f" {'ORACLE: true per-application speedup':42s} median {np.median(e):.3f}")
print("\nInterpretation:")
print(" The gap between the fitted-global row and the ORACLE row is what a")
print(" perfect machine model could add. The gap between lscpu and fitted-")
print(" global is what knowing the specs buys over knowing nothing. If lscpu")
print(" is no better than a fitted constant, the specs are carrying no")
print(" information beyond 'this machine is faster by roughly X'.")