Skip to content

Commit 579e0de

Browse files
committed
diag(power): preflight v3 tolerant amd-smi json parsing + raw dumps
中文:v2 判决 FAIL 实为 parser 与 AMDSMI 26.2.0 输出结构不匹配(延迟 p95=80ms 极好);v3 兼容 value/unit 嵌套与多种顶层结构,并把 metric/static 原始 JSON 头部存入报告以便离线定位。
1 parent 428175b commit 579e0de

1 file changed

Lines changed: 43 additions & 11 deletions

File tree

‎utils/mi355x_power_preflight.py‎

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ def run_json(cmd, timeout=30):
3131
return dt, rc, None, (err or out)[:500]
3232

3333

34+
def gpu_entries(doc):
35+
if isinstance(doc, list):
36+
return doc
37+
if isinstance(doc, dict):
38+
if isinstance(doc.get("gpu"), list):
39+
return doc["gpu"]
40+
if all(isinstance(v, dict) for v in doc.values()) and doc:
41+
return [dict(v, gpu=k) for k, v in doc.items()]
42+
return []
43+
44+
45+
def num(x):
46+
if isinstance(x, dict):
47+
x = x.get("value")
48+
return x if isinstance(x, (int, float)) else None
49+
50+
51+
def pick(sec, keys):
52+
if not isinstance(sec, dict):
53+
return None
54+
for k in keys:
55+
v = num(sec.get(k))
56+
if v is not None:
57+
return v
58+
return None
59+
60+
61+
POWER_KEYS = ["socket_power", "average_socket_power", "current_socket_power", "power"]
62+
ENERGY_KEYS = ["total_energy_consumption", "energy_accumulator", "total_energy"]
63+
64+
3465
def main():
3566
ap = argparse.ArgumentParser()
3667
ap.add_argument("--samples", type=int, default=60)
@@ -52,12 +83,14 @@ def main():
5283
ck["version"] = {"ok": rc == 0, "value": ver, "err": err if rc else None}
5384

5485
dt, rc, static, err = run_json(["amd-smi", "static"])
86+
_, _, static_raw, _ = run(["amd-smi", "static", "--json"])
87+
report["raw"]["static_head"] = (static_raw or "")[:3000]
5588
identity = {}
5689
if rc == 0 and static:
57-
for gpu in static if isinstance(static, list) else static.get("gpu", []):
90+
for gpu in gpu_entries(static):
5891
idx = gpu.get("gpu")
59-
asic = gpu.get("asic", {})
60-
board = gpu.get("board", {})
92+
asic = gpu.get("asic", {}) or {}
93+
board = gpu.get("board", {}) or {}
6194
identity[str(idx)] = {
6295
"asic_serial": asic.get("asic_serial"),
6396
"market_name": asic.get("market_name"),
@@ -68,12 +101,13 @@ def main():
68101
dt, rc, uuid_out, err = run(["amd-smi", "list", "-e"])
69102
report["raw"]["list_e_head"] = (uuid_out or err or "")[:800]
70103

104+
dt, rc2, metric_raw, err = run(["amd-smi", "metric", "-p", "-E", "--json"])
105+
report["raw"]["metric_p_E_head"] = (metric_raw or err or "")[:4000]
71106
dt, rc, one, err = run_json(["amd-smi", "metric", "-p", "-E"])
72107
fields = set()
73108
if rc == 0 and one:
74-
for gpu in one if isinstance(one, list) else one.get("gpu", []):
75-
for section in ("power", "energy"):
76-
sec = gpu.get(section)
109+
for gpu in gpu_entries(one):
110+
for section, sec in gpu.items():
77111
if isinstance(sec, dict):
78112
fields.update(f"{section}.{k}" for k in sec)
79113
ck["power_energy_fields"] = {"ok": bool(fields), "fields": sorted(fields)}
@@ -86,13 +120,11 @@ def main():
86120
lat.append(dt)
87121
row = {"t": time.monotonic() - t_start, "rc": rc, "gpus": {}}
88122
if rc == 0 and snap:
89-
for gpu in snap if isinstance(snap, list) else snap.get("gpu", []):
123+
for gpu in gpu_entries(snap):
90124
idx = str(gpu.get("gpu"))
91-
pw = (gpu.get("power") or {})
92-
en = (gpu.get("energy") or {})
93125
row["gpus"][idx] = {
94-
"socket_power": pw.get("socket_power"),
95-
"energy_accumulator": en.get("total_energy_consumption"),
126+
"socket_power": pick(gpu.get("power"), POWER_KEYS),
127+
"energy_accumulator": pick(gpu.get("energy"), ENERGY_KEYS),
96128
}
97129
series.append(row)
98130
sleep_for = (i + 1) * interval - (time.monotonic() - t_start)

0 commit comments

Comments
 (0)