Skip to content

Commit 3e8fa8f

Browse files
committed
final
Signed-off-by: Yang Wang <[email protected]>
1 parent 057558f commit 3e8fa8f

File tree

4 files changed

+253
-0
lines changed

4 files changed

+253
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
import requests
3+
import pandas as pd
4+
import json
5+
from datetime import datetime
6+
from read_benchmark_data import build_query_params
7+
8+
def fetch_llm_data(payload: dict) -> list:
9+
url = "https://hud.pytorch.org/api/clickhouse/oss_ci_benchmark_llms"
10+
headers = {"Content-Type": "application/json"}
11+
response = requests.post(url, headers=headers, data=json.dumps(payload))
12+
response.raise_for_status()
13+
return response.json()
14+
15+
def flatten_record(record):
16+
flat = {
17+
"timestamp": record.get("metadata_info", {}).get("timestamp"),
18+
"workflow_id": record.get("workflow_id"),
19+
"job_id": record.get("job_id"),
20+
"model": record.get("model"),
21+
"backend": record.get("backend"),
22+
"mode": record.get("mode"),
23+
"dtype": record.get("dtype"),
24+
"device": record.get("device"),
25+
"arch": record.get("arch"),
26+
"granularity_bucket": record.get("granularity_bucket"),
27+
}
28+
if "extra" in record:
29+
for k, v in record["extra"].items():
30+
flat[f"extra_{k}"] = v
31+
metric_name = record["metric"]
32+
flat[metric_name] = record["actual"]
33+
return flat
34+
35+
def process_records(data: list) -> pd.DataFrame:
36+
flattened = [flatten_record(entry) for entry in data]
37+
df = pd.DataFrame(flattened)
38+
id_cols = [
39+
"timestamp", "workflow_id", "job_id", "model", "backend", "mode", "dtype",
40+
"device", "arch", "granularity_bucket",
41+
"extra_use_torch_compile", "extra_is_dynamic",
42+
"extra_request_rate", "extra_tensor_parallel_size"
43+
]
44+
df = df.groupby(id_cols, dropna=False).first().reset_index()
45+
return df
46+
47+
def main():
48+
props = {
49+
"archName": "All Platforms",
50+
"deviceName": "Samsung Galaxy S22 5G (private) (Android 13)",
51+
"modeName": "inference",
52+
"modelName": "mv3",
53+
"backendName": "qnn_q8",
54+
"benchmarkName": "", # fallback to repo default
55+
"repoName": "pytorch/executorch",
56+
"granularity": "hour",
57+
"startTime": datetime(2025, 5, 23, 1, 1, 22),
58+
"stopTime": datetime(2025, 6, 6, 1, 1, 22),
59+
"branch": "main",
60+
"commit": "098c58e1adc082ad98ffd6efb41151736fbc1a12"
61+
}
62+
dtypes = [""]
63+
64+
payload = build_query_params(props, dtypes)
65+
print("Query payload:")
66+
print(json.dumps(payload, indent=2))
67+
68+
data = fetch_llm_data(payload)
69+
df = process_records(data)
70+
71+
df.to_csv("llm_benchmark_result.csv", index=False)
72+
print(df.head())
73+
74+
if __name__ == "__main__":
75+
main()
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import datetime
2+
from pprint import pprint
3+
from typing import Any
4+
from dataclasses import dataclass, asdict
5+
import json
6+
import requests
7+
from urllib.parse import urlencode
8+
import argparse
9+
10+
@dataclass
11+
class BenchmarkQueryGroupDataParams:
12+
repo: str
13+
benchmark_name: str
14+
start_time: str
15+
end_time: str
16+
group_table_by_fields: list
17+
group_row_by_fields: list
18+
19+
BASE_URLS = {
20+
"local": "http://localhost:3000",
21+
"prod": "https://hud.pytorch.org",
22+
}
23+
24+
def validate_iso8601_no_ms(value):
25+
try:
26+
# Only allow format without milliseconds
27+
return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S")
28+
except ValueError:
29+
raise argparse.ArgumentTypeError(
30+
f"Invalid datetime format for '{value}'. Expected: YYYY-MM-DDTHH:MM:SS"
31+
)
32+
33+
def argparser():
34+
parser = argparse.ArgumentParser()
35+
parser.add_argument(
36+
"--env", choices=["local", "prod"], default="prod", help="Choose environment"
37+
)
38+
parser.add_argument(
39+
"--startTime",
40+
type=validate_iso8601_no_ms,
41+
required=True,
42+
help="Start time in ISO format (e.g. 2025-06-01T00:00:00)",
43+
)
44+
parser.add_argument(
45+
"--endTime",
46+
type=validate_iso8601_no_ms,
47+
required=True,
48+
help="End time in ISO format (e.g. 2025-06-06T00:00:00)",
49+
)
50+
return parser.parse_args()
51+
52+
53+
BASE_URLS = {
54+
"local": "http://localhost:3000",
55+
"prod": "https://hud.pytorch.org",
56+
}
57+
58+
59+
def fetch_execu_torch_data(startTime: str, endTime: str, env: str = 'prod'):
60+
url = f"{BASE_URLS[env]}/api/benchmark/group_data/execuTorch"
61+
# Convert back to string in the same format 2025-06-01T00:00:00
62+
start_time_str = startTime
63+
end_time_str = endTime
64+
65+
params_object = BenchmarkQueryGroupDataParams(
66+
repo="pytorch/executorch",
67+
benchmark_name="ExecuTorch",
68+
start_time=start_time_str,
69+
end_time=end_time_str,
70+
group_table_by_fields=["device", "backend", "arch", "model"],
71+
group_row_by_fields=["workflow_id", "job_id", "granularity_bucket"],
72+
)
73+
74+
# Convert to JSON string
75+
params = json.dumps(asdict(params_object))
76+
response = requests.get(url, params=params)
77+
if response.status_code == 200:
78+
print("Successfully fetched benchmark data")
79+
resp = response.json()
80+
print(f"fetched {len(resp)} table views")
81+
print(f"peeking first table view, peeking.... {resp[0]} ")
82+
else:
83+
print(f"Failed to fetch benchmark data ({response.status_code})")
84+
print(response.text)
85+
86+
87+
88+
89+
def main():
90+
args = argparser()
91+
fetch_execu_torch_data(args.startTime, args.endTime, args.env)
92+
93+
if __name__ == "__main__":
94+
main()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import pandas as pd
2+
3+
DEFAULT_ARCH_NAME = "All Platforms"
4+
DEFAULT_DEVICE_NAME = "All Devices"
5+
DEFAULT_MODE_NAME = "All Modes"
6+
DEFAULT_MODEL_NAME = "All Models"
7+
DEFAULT_BACKEND_NAME = "All Backends"
8+
9+
EXCLUDED_METRICS = [
10+
"load_status", "mean_itl_ms", "mean_tpot_ms", "mean_ttft_ms",
11+
"std_itl_ms", "std_tpot_ms", "std_ttft_ms",
12+
"cold_compile_time(s)", "warm_compile_time(s)",
13+
"speedup_pct", "generate_time(ms)"
14+
]
15+
16+
REPO_TO_BENCHMARKS = {
17+
"pytorch/executorch": ["ExecuTorch"],
18+
# 其他 repo 可继续加
19+
}
20+
21+
from datetime import datetime
22+
23+
def format_time(dt: datetime) -> str:
24+
return dt.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
25+
26+
from typing import Dict, Any
27+
28+
def build_query_params(props: Dict[str, Any], dtypes: list) -> dict:
29+
return {
30+
"arch": "" if props["archName"] == DEFAULT_ARCH_NAME else props["archName"],
31+
"device": "" if props["deviceName"] == DEFAULT_DEVICE_NAME else props["deviceName"],
32+
"mode": "" if props["modeName"] == DEFAULT_MODE_NAME else props["modeName"],
33+
"dtypes": dtypes,
34+
"excludedMetrics": EXCLUDED_METRICS,
35+
"benchmarks": [props["benchmarkName"]] if props.get("benchmarkName") else REPO_TO_BENCHMARKS.get(props["repoName"], []),
36+
"granularity": props["granularity"],
37+
"models": [] if props["modelName"] == DEFAULT_MODEL_NAME else [props["modelName"]],
38+
"backends": [] if props["backendName"] == DEFAULT_BACKEND_NAME else [props["backendName"]],
39+
"repo": props["repoName"],
40+
"startTime": format_time(props["startTime"]),
41+
"stopTime": format_time(props["stopTime"]),
42+
}
43+
44+
def flatten_record(record):
45+
flat = {
46+
"timestamp": record.get("metadata_info", {}).get("timestamp"),
47+
"workflow_id": record.get("workflow_id"),
48+
"job_id": record.get("job_id"),
49+
"model": record.get("model"),
50+
"backend": record.get("backend"),
51+
"mode": record.get("mode"),
52+
"dtype": record.get("dtype"),
53+
"device": record.get("device"),
54+
"arch": record.get("arch"),
55+
"granularity_bucket": record.get("granularity_bucket"),
56+
}
57+
58+
# Flatten extra
59+
if "extra" in record:
60+
for k, v in record["extra"].items():
61+
flat[f"extra_{k}"] = v
62+
63+
# Add metric-specific value
64+
metric_name = record["metric"]
65+
flat[metric_name] = record["actual"]
66+
67+
return flat
68+
69+
def process_records(data: list) -> pd.DataFrame:
70+
flattened = [flatten_record(entry) for entry in data]
71+
df = pd.DataFrame(flattened)
72+
73+
# Group by workflow_id, job_id, timestamp
74+
id_cols = [
75+
"timestamp", "workflow_id", "job_id", "model", "backend", "mode", "dtype",
76+
"device", "arch", "granularity_bucket",
77+
"extra_use_torch_compile", "extra_is_dynamic",
78+
"extra_request_rate", "extra_tensor_parallel_size"
79+
]
80+
81+
df = df.groupby(id_cols, dropna=False).first().reset_index()
82+
83+
return df
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests>=2.32.3

0 commit comments

Comments
 (0)