Repository navigation
Expand file tree
/
Copy pathparse_gpu_perf.py
More file actions
145 lines (118 loc) · 4.38 KB
/
Copy pathparse_gpu_perf.py
File metadata and controls
145 lines (118 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import argparse
import ast
import json
import re
from pathlib import Path
from typing import Any
DEFAULT_INPUT_DIR = Path("data/gpu_perf")
DEFAULT_OUTPUT = Path("data/gpu_perf_records.jsonl")
NAMESPACE_RE = re.compile(r"^Namespace\((?P<body>.*)\)$")
ITERATION_RE = re.compile(
r"^Iteration (?P<iteration>\d+), "
r"(?P<images_per_second>\d+(?:\.\d+)?) images/s in "
r"(?P<seconds>\d+(?:\.\d+)?)s\.?$"
)
def parse_namespace(line: str) -> dict[str, Any]:
match = NAMESPACE_RE.match(line.strip())
if not match:
raise ValueError(f"not a Namespace line: {line!r}")
values: dict[str, Any] = {}
for part in re.split(r",\s*", match.group("body")):
if not part:
continue
key, raw_value = part.split("=", 1)
try:
value = ast.literal_eval(raw_value)
except (SyntaxError, ValueError):
value = raw_value
values[key] = value
return values
def parse_gpu_perf_text(
text: str,
gpu_id: str | None = None,
source_file: str | None = None,
) -> list[dict[str, Any]]:
hardware_model: str | None = None
framework: str | None = None
benchmark: str | None = None
context: dict[str, Any] = {}
records: list[dict[str, Any]] = []
for raw_line in text.splitlines():
line = raw_line.strip()
if not line:
continue
if line.startswith("GPU 具体型号为:"):
hardware_model = line.split(":", 1)[1].strip()
continue
if line.startswith("使用"):
framework = line.removeprefix("使用").strip()
continue
if line.startswith(">>>"):
benchmark = line.removeprefix(">>>").strip()
context = {}
continue
if NAMESPACE_RE.match(line):
context = parse_namespace(line)
continue
iteration_match = ITERATION_RE.match(line)
if iteration_match:
if benchmark is None:
raise ValueError(f"iteration without benchmark context: {line!r}")
if not context:
raise ValueError(f"iteration without Namespace context: {line!r}")
record = {
"gpu_id": gpu_id,
"source_file": source_file,
"hardware_model": hardware_model,
"framework": framework,
"benchmark": benchmark,
"model": context.get("model"),
"precision": context.get("precision"),
"train": context.get("train"),
"device": context.get("device"),
"iteration": int(iteration_match.group("iteration")),
"images_per_second": float(iteration_match.group("images_per_second")),
"seconds": float(iteration_match.group("seconds")),
}
records.append(record)
return records
def parse_gpu_perf_file(path: Path) -> list[dict[str, Any]]:
return parse_gpu_perf_text(
path.read_text(encoding="utf-8"),
gpu_id=path.stem,
source_file=str(path),
)
def parse_gpu_perf_dir(input_dir: Path) -> list[dict[str, Any]]:
records: list[dict[str, Any]] = []
for path in sorted(input_dir.glob("*.txt")):
records.extend(parse_gpu_perf_file(path))
return records
def write_jsonl(records: list[dict[str, Any]], output_path: Path) -> None:
output_path.parent.mkdir(parents=True, exist_ok=True)
with output_path.open("w", encoding="utf-8") as f:
for record in records:
f.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n")
def main() -> None:
parser = argparse.ArgumentParser(
description="Parse AutoDL GPU performance text logs into JSONL iteration records."
)
parser.add_argument(
"--input-dir",
default=str(DEFAULT_INPUT_DIR),
help="Directory containing GPU_ID.txt performance logs.",
)
parser.add_argument(
"--output",
default=str(DEFAULT_OUTPUT),
help="JSONL output path. Use '-' to print to stdout.",
)
args = parser.parse_args()
records = parse_gpu_perf_dir(Path(args.input_dir))
if args.output == "-":
for record in records:
print(json.dumps(record, ensure_ascii=False, sort_keys=True))
else:
write_jsonl(records, Path(args.output))
print(f"Wrote {len(records)} records to {args.output}")
if __name__ == "__main__":
main()