power-report: --results and --label for cross-machine comparison graph

Same knobs as compare-report, so the package-power/CPU-temp overlay can be
drawn from a collected results directory with friendly machine names.
This commit is contained in:
smill 2026-09-30 00:05:29 -04:00
commit a2475a1ba3

View file

@ -101,9 +101,25 @@ def window(series, lo, hi):
def main(): def main():
global RES, GRAPHS
ap = argparse.ArgumentParser() ap = argparse.ArgumentParser()
ap.add_argument("--tags", nargs="+", required=True) ap.add_argument("--tags", nargs="+", required=True)
ap.add_argument("--results", default=RES, help="results directory (default ./results)")
ap.add_argument("--label", action="append", default=[], metavar="TAG=NAME",
help="friendly name for a tag in the comparison graph (repeatable)")
args = ap.parse_args() args = ap.parse_args()
RES = os.path.abspath(args.results)
GRAPHS = os.path.join(RES, "graphs")
labels = {}
for spec in args.label:
if "=" in spec:
k, v = spec.split("=", 1)
labels[k] = v
def label(t):
return labels.get(t, t)
os.makedirs(GRAPHS, exist_ok=True) os.makedirs(GRAPHS, exist_ok=True)
data = {} data = {}
@ -128,12 +144,12 @@ def main():
t0 = pkg[0][0] t0 = pkg[0][0]
cpu = d["cpu"] or "unknown CPU" cpu = d["cpu"] or "unknown CPU"
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7), sharex=True) fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7), sharex=True)
for label, series, color in (("package W", d["pkg"], "#c0392b"), for series_label, series, color in (("package W", d["pkg"], "#c0392b"),
("core W", d["core"], "#e67e22"), ("core W", d["core"], "#e67e22"),
("GPU W", d["gpu"], "#2980b9")): ("GPU W", d["gpu"], "#2980b9")):
pts = [((t - t0) / 60, v) for t, v in series if v is not None] pts = [((t - t0) / 60, v) for t, v in series if v is not None]
if pts: if pts:
ax1.plot([p[0] for p in pts], [p[1] for p in pts], label=label, color=color, lw=1) ax1.plot([p[0] for p in pts], [p[1] for p in pts], label=series_label, color=color, lw=1)
ax1.set_ylabel("power (W)") ax1.set_ylabel("power (W)")
ax1.legend(loc="upper right", fontsize=8) ax1.legend(loc="upper right", fontsize=8)
ax1.set_title(f"power & thermal profile — {tag}\nCPU: {cpu}") ax1.set_title(f"power & thermal profile — {tag}\nCPU: {cpu}")
@ -213,15 +229,15 @@ def main():
continue continue
t0 = d["pkg"][0][0] t0 = d["pkg"][0][0]
pts = [((t - t0) / 60, v) for t, v in d["pkg"] if v is not None] pts = [((t - t0) / 60, v) for t, v in d["pkg"] if v is not None]
ax1.plot([p[0] for p in pts], [p[1] for p in pts], label=tag, color=color, lw=1) ax1.plot([p[0] for p in pts], [p[1] for p in pts], label=label(tag), color=color, lw=1)
tt = [((t - t0) / 60, v) for t, v in d["temp"] if v is not None] tt = [((t - t0) / 60, v) for t, v in d["temp"] if v is not None]
if tt: if tt:
ax2.plot([p[0] for p in tt], [p[1] for p in tt], label=tag, color=color, lw=1) ax2.plot([p[0] for p in tt], [p[1] for p in tt], label=label(tag), color=color, lw=1)
ax1.set_ylabel("package W") ax1.set_ylabel("package W")
ax1.legend(fontsize=8) ax1.legend(fontsize=8)
cpus = [data[t]["cpu"] for t in args.tags if data[t]["cpu"]] cpus = [data[t]["cpu"] for t in args.tags if data[t]["cpu"]]
cpu_note = " | ".join(dict.fromkeys(cpus)) if cpus else "unknown CPU" cpu_note = " | ".join(dict.fromkeys(cpus)) if cpus else "unknown CPU"
ax1.set_title(f"BEFORE vs AFTER — package power & CPU temp\nCPUs: {cpu_note}") ax1.set_title(f"package power & CPU temp — {len(args.tags)} runs\nCPUs: {cpu_note}")
ax1.grid(alpha=0.3) ax1.grid(alpha=0.3)
ax2.set_ylabel("CPU temp (°C)") ax2.set_ylabel("CPU temp (°C)")
ax2.set_xlabel("minutes from start") ax2.set_xlabel("minutes from start")