Skip to content

Commit 8cbb5f0

Browse files
authored
[Compiler time series data] Add fetch raw data logics (#7137)
support fetch raw data as time series for compiler data support arch mapping between the db and api make the query logics as commits driven 1. if commits is provided in api, then fetch data using the list of commits 2. if not provided, use startTime stopTime to fetch list of unique commits, then fetch the time series data
1 parent 05023d3 commit 8cbb5f0

16 files changed

Lines changed: 654 additions & 258 deletions

File tree

aws/lambda/benchmark_regression_summary_report/common/regression_utils.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,18 @@ def detect_regressions_with_policies(
128128
logger.info("Generating regression results ...")
129129
results: List[PerGroupResult] = []
130130

131+
missing_policy = set() # for logging
132+
131133
for key in sorted(dp_map.keys()):
132134
cur_item = dp_map.get(key)
133135
gi = cur_item["group_info"] if cur_item else {}
134136
points: List[Any] = cur_item["values"] if cur_item else []
135137

138+
policy = self._resolve_policy(metric_policies, gi.get("metric", ""))
139+
if not policy:
140+
missing_policy.add(gi.get("metric", ""))
141+
continue
142+
136143
base_item = baseline_map.get(key)
137144
if not base_item:
138145
logger.warning("Skip. No baseline item found for %s", key)
@@ -147,20 +154,6 @@ def detect_regressions_with_policies(
147154
)
148155
)
149156
continue
150-
policy = self._resolve_policy(metric_policies, gi.get("metric", ""))
151-
if not policy:
152-
logger.warning("No policy for %s", gi)
153-
results.append(
154-
PerGroupResult(
155-
group_info=gi,
156-
baseline_point=None,
157-
points=[],
158-
label="insufficient_data",
159-
policy=None,
160-
all_baseline_points=[],
161-
)
162-
)
163-
continue
164157
baseline_aggre_mode = policy.baseline_aggregation
165158
baseline_result = self._get_baseline(base_item, baseline_aggre_mode)
166159
if (
@@ -208,6 +201,11 @@ def detect_regressions_with_policies(
208201
logger.info("Done. Generated %s regression results", len(results))
209202
summary = self.summarize_label_counts(results)
210203

204+
logger.info(
205+
"Found metrics existed in data, but no regression policy detected: %s",
206+
missing_policy,
207+
)
208+
211209
return BenchmarkRegressionReport(
212210
summary=summary,
213211
results=results,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"params": {
3+
"branches": "Array(String)",
4+
"device": "String",
5+
"arch": "Array(String)",
6+
"dtype": "String",
7+
"mode": "String",
8+
"startTime": "DateTime64(3)",
9+
"stopTime": "DateTime64(3)",
10+
"suites": "Array(String)",
11+
"workflowIds": "Array(Int64)"
12+
},
13+
"tests": []
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
SELECT DISTINCT
2+
replaceOne(head_branch, 'refs/heads/', '') AS branch,
3+
head_sha AS commit,
4+
workflow_id AS id,
5+
timestamp
6+
FROM benchmark.oss_ci_benchmark_torchinductor
7+
PREWHERE
8+
timestamp >= toUnixTimestamp({startTime: DateTime64(3)})
9+
AND timestamp < toUnixTimestamp({stopTime: DateTime64(3)})
10+
WHERE
11+
(
12+
has(
13+
{branches: Array(String)},
14+
replaceOne(head_branch, 'refs/heads/', '')
15+
)
16+
OR empty({branches: Array(String)})
17+
)
18+
AND (
19+
has({suites: Array(String) }, suite)
20+
OR empty({suites: Array(String) })
21+
)
22+
AND benchmark_dtype = {dtype: String}
23+
AND benchmark_mode = {mode: String}
24+
AND device = {device: String}
25+
AND multiSearchAnyCaseInsensitive(arch, {arch: Array(String)})
26+
ORDER BY timestamp
27+
SETTINGS session_timezone = 'UTC';

torchci/clickhouse_queries/compilers_benchmark_api_query/params.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44
"commits": "Array(String)",
55
"compilers": "Array(String)",
66
"device": "String",
7-
"arch": "String",
7+
"arch": "Array(String)",
88
"dtype": "String",
99
"granularity": "String",
1010
"mode": "String",
11-
"startTime": "DateTime64(3)",
12-
"stopTime": "DateTime64(3)",
13-
"suites": "Array(String)",
14-
"workflowId": "Int64"
11+
"suites": "Array(String)"
1512
},
1613
"tests": []
1714
}
Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
SELECT
22
workflow_id,
33
job_id,
4-
head_sha,
5-
replaceOne(head_branch, 'refs/heads/', '') AS head_branch,
4+
head_sha AS commit,
5+
replaceOne(head_branch, 'refs/heads/', '') AS branch,
66
suite,
77
model_name AS model,
88
metric_name AS metric,
99
value,
1010
metric_extra_info AS extra_info,
1111
benchmark_extra_info['output'] AS output,
12+
benchmark_dtype AS dtype,
13+
benchmark_mode AS mode,
14+
device,
15+
arch,
1216
timestamp,
1317
DATE_TRUNC({granularity: String}, fromUnixTimestamp(timestamp))
1418
AS granularity_bucket
1519
FROM benchmark.oss_ci_benchmark_torchinductor
1620
WHERE
17-
(head_sha) IN (
18-
SELECT DISTINCT head_sha
19-
FROM benchmark.oss_ci_benchmark_torchinductor
20-
PREWHERE
21-
timestamp >= toUnixTimestamp({startTime: DateTime64(3,)})
22-
AND timestamp < toUnixTimestamp({stopTime: DateTime64(3)})
23-
)
21+
head_sha IN ({commits: Array(String)})
2422
AND (
2523
has(
2624
{branches: Array(String)},
2725
replaceOne(head_branch, 'refs/heads/', '')
2826
)
2927
OR empty({branches: Array(String)})
3028
)
29+
AND (
30+
has({suites: Array(String) }, suite)
31+
OR empty({suites: Array(String) })
32+
)
3133
AND benchmark_dtype = {dtype: String}
3234
AND benchmark_mode = {mode: String}
3335
AND device = {device: String}
34-
AND positionCaseInsensitive(arch, {arch: String}) > 0
35-
36+
AND multiSearchAnyCaseInsensitive(arch, {arch: Array(String)})
37+
ORDER BY timestamp
3638
SETTINGS session_timezone = 'UTC';
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { queryClickhouseSaved } from "lib/clickhouse";
2+
import { emptyTimeSeriesResponse } from "../utils";
3+
import {
4+
extractBackendSqlStyle,
5+
toApiArch,
6+
toQueryArch,
7+
} from "./helpers/common";
8+
import { toGeneralCompilerData } from "./helpers/general";
9+
import { toPrecomputeCompilerData } from "./helpers/precompute";
10+
import { CompilerQueryType } from "./type";
11+
//["x86_64","NVIDIA A10G","NVIDIA H100 80GB HBM3"]
12+
const COMPILER_BENCHMARK_TABLE_NAME = "compilers_benchmark_api_query";
13+
const COMPILER_BENCHMARK_COMMITS_TABLE_NAME =
14+
"compilers_benchmark_api_commit_query";
15+
16+
export async function getCompilerBenchmarkData(
17+
inputparams: any,
18+
type: CompilerQueryType = CompilerQueryType.PRECOMPUTE,
19+
format: string = "time_series"
20+
) {
21+
const rows = await getCompilerDataFromClickhouse(inputparams);
22+
23+
if (rows.length === 0) {
24+
return emptyTimeSeriesResponse();
25+
}
26+
27+
switch (type) {
28+
case CompilerQueryType.PRECOMPUTE:
29+
return toPrecomputeCompilerData(rows, format);
30+
case CompilerQueryType.GENERAL:
31+
return toGeneralCompilerData(rows, format);
32+
default:
33+
throw new Error(`Invalid compiler query type, got ${type}`);
34+
}
35+
}
36+
37+
async function getCompilerDataFromClickhouse(inputparams: any): Promise<any[]> {
38+
const start = Date.now();
39+
const arch_list = toQueryArch(inputparams.device, inputparams.arch);
40+
inputparams["arch"] = arch_list;
41+
42+
// use the startTime and endTime to fetch commits from clickhouse if commits field is not provided
43+
if (!inputparams.commits || inputparams.commits.length == 0) {
44+
if (!inputparams.startTime || !inputparams.stopTime) {
45+
console.log("no commits or start/end time provided in request");
46+
return [];
47+
}
48+
// get commits from clickhouse
49+
const commit_results = await queryClickhouseSaved(
50+
COMPILER_BENCHMARK_COMMITS_TABLE_NAME,
51+
inputparams
52+
);
53+
// get unique commits
54+
const unique_commits = [...new Set(commit_results.map((c) => c.commit))];
55+
if (unique_commits.length === 0) {
56+
console.log("no commits found in clickhouse using", inputparams);
57+
return [];
58+
}
59+
60+
console.log(
61+
"no commits provided in request, found unqiue commits",
62+
unique_commits
63+
);
64+
65+
if (commit_results.length > 0) {
66+
inputparams["commits"] = unique_commits;
67+
} else {
68+
console.log(`no commits found in clickhouse using ${inputparams}`);
69+
return [];
70+
}
71+
} else {
72+
console.log("commits provided in request", inputparams.commits);
73+
}
74+
75+
let rows = await queryClickhouseSaved(
76+
COMPILER_BENCHMARK_TABLE_NAME,
77+
inputparams
78+
);
79+
const end = Date.now();
80+
console.log("time to get compiler timeseris data", end - start);
81+
82+
if (rows.length === 0) {
83+
return [];
84+
}
85+
86+
// extract backend from output in runtime instead of doing it in the query. since it's expensive for regex matching.
87+
// TODO(elainewy): we should add this as a column in the database for less runtime logics.
88+
rows.map((row) => {
89+
const backend =
90+
row.backend && row.backend !== ""
91+
? row.backend
92+
: extractBackendSqlStyle(
93+
row.output,
94+
row.suite,
95+
row.dtype,
96+
row.mode,
97+
row.device
98+
);
99+
(row["backend"] = backend), (row["compiler"] = backend);
100+
row["arch"] = toApiArch(row.device, row.arch);
101+
});
102+
103+
if (inputparams.compilers && inputparams.compilers.length > 0) {
104+
rows = rows.filter((row) => {
105+
return inputparams.compilers.includes(row.backend);
106+
});
107+
}
108+
109+
if (inputparams.models && inputparams.models.length > 0) {
110+
rows = rows.filter((row) => {
111+
return inputparams.models.includes(row.model);
112+
});
113+
}
114+
115+
if (inputparams.metrics && inputparams.metrics.length > 0) {
116+
rows = rows.filter((row) => {
117+
return inputparams.metrics.includes(row.metric);
118+
});
119+
}
120+
return rows;
121+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { groupByBenchmarkData } from "../../utils";
2+
3+
export function to_table_compiler_data(data: any[]) {
4+
const res = groupByBenchmarkData(
5+
data,
6+
["dtype", "arch", "device", "mode", "workflow_id", "granularity_bucket"],
7+
["metric", "compiler"]
8+
);
9+
return res;
10+
}
11+
12+
export function extractBackendSqlStyle(
13+
output: string,
14+
suite: string,
15+
dtype: string,
16+
mode: string,
17+
device: string
18+
): string | null {
19+
const esc = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20+
const tail = `_${esc(suite)}_${esc(dtype)}_${esc(mode)}_${esc(device)}_`;
21+
22+
const temp = output.replace(new RegExp(`${tail}.*$`), "");
23+
24+
const m = temp.match(/.*[\/\\]([^\/\\]+)$/);
25+
return m ? m[1] : null;
26+
}
27+
28+
export function toQueryArch(device: string, arch: string) {
29+
switch (device) {
30+
case "rocm":
31+
if (arch === "mi300x") return ["mi300x", "mi325x"];
32+
return [arch];
33+
default:
34+
return [arch];
35+
}
36+
}
37+
38+
export function toApiArch(device: string, arch: string): string {
39+
const norm = arch.toLowerCase();
40+
switch (device) {
41+
case "cpu":
42+
return norm;
43+
case "cuda":
44+
if (norm.includes("h100")) return "h100";
45+
if (norm.includes("a100")) return "a100";
46+
if (norm.includes("a10g")) return "a10g";
47+
if (norm.includes("b200")) return "b200";
48+
return norm;
49+
case "rocm":
50+
if (norm.includes("mi300x")) return "mi300x";
51+
if (norm.includes("mi325x")) return "mi300x";
52+
return norm;
53+
case "mps":
54+
return norm;
55+
default:
56+
return norm;
57+
}
58+
}
59+
60+
function deepDiff(obj1: any, obj2: any) {
61+
const diffs: string[] = [];
62+
const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
63+
for (const key of allKeys) {
64+
const v1 = obj1[key];
65+
const v2 = obj2[key];
66+
if (
67+
typeof v1 === "object" &&
68+
v1 !== null &&
69+
typeof v2 === "object" &&
70+
v2 !== null
71+
) {
72+
if (JSON.stringify(v1) !== JSON.stringify(v2)) {
73+
diffs.push(
74+
`Key "${key}" differs: ${JSON.stringify(v1)} vs ${JSON.stringify(v2)}`
75+
);
76+
}
77+
} else if (v1 !== v2) {
78+
diffs.push(`Key "${key}" differs: ${v1} vs ${v2}`);
79+
}
80+
}
81+
82+
return diffs;
83+
}

0 commit comments

Comments
 (0)