Skip to content

Commit 6070d43

Browse files
liyuying0000copybara-github
authored andcommitted
No public description
PiperOrigin-RevId: 728430566 Change-Id: If18c6eef37852be4e48000ff0c2d30c36e0ca592
1 parent 7a7de6a commit 6070d43

File tree

5 files changed

+374
-123
lines changed

5 files changed

+374
-123
lines changed

fleetbench/parallel/BUILD

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ py_library(
5656
deps = [
5757
":benchmark",
5858
":cpu",
59-
":result",
59+
":reporter",
6060
":run",
6161
":worker",
6262
"@com_google_absl_py//absl/logging",
@@ -65,6 +65,15 @@ py_library(
6565
],
6666
)
6767

68+
py_library(
69+
name = "reporter",
70+
srcs = ["reporter.py"],
71+
deps = [
72+
"@com_google_absl_py//absl/logging",
73+
requirement("pandas"),
74+
],
75+
)
76+
6877
py_binary(
6978
name = "parallel_bench",
7079
testonly = True,
@@ -86,6 +95,7 @@ py_test(
8695
":benchmark",
8796
":cpu",
8897
":parallel_bench_lib",
98+
":reporter",
8999
":result",
90100
":run",
91101
"@com_google_absl_py//absl/testing:absltest",
@@ -134,3 +144,13 @@ py_test(
134144
"@com_google_absl_py//absl/testing:flagsaver",
135145
],
136146
)
147+
148+
py_test(
149+
name = "reporter_test",
150+
srcs = ["reporter_test.py"],
151+
deps = [
152+
":reporter",
153+
"@com_google_absl_py//absl/testing:absltest",
154+
requirement("pandas"),
155+
],
156+
)

fleetbench/parallel/parallel_bench_lib.py

Lines changed: 3 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from fleetbench.parallel import benchmark as bm
2828
from fleetbench.parallel import cpu
29+
from fleetbench.parallel import reporter
2930
from fleetbench.parallel import run
3031
from fleetbench.parallel import worker
3132

@@ -308,76 +309,6 @@ def _RunSchedulingLoop(self) -> None:
308309
)
309310
)
310311

311-
def GenerateBenchmarkReport(
312-
self,
313-
df: pd.DataFrame,
314-
perf_counter_df: pd.DataFrame | None,
315-
) -> pd.DataFrame:
316-
"""Generates a DataFrame of aggregated benchmark results.
317-
318-
Args:
319-
df: A DataFrame of benchmark results.
320-
perf_counter_df: A DataFrame of performance counter results.
321-
322-
Returns:
323-
A DataFrame of aggregated benchmark results.
324-
"""
325-
326-
# Remove "fleetbench (" prefix and ")" suffix
327-
df["Benchmark"] = (
328-
df["Benchmark"]
329-
.astype(str)
330-
.str.replace(r"fleetbench \((.*)\)", r"\1", regex=True)
331-
)
332-
333-
grouped_results = (
334-
df.groupby("Benchmark")
335-
.agg(
336-
Count=("WallTimes", "count"),
337-
Mean_Wall_Time=("WallTimes", "mean"),
338-
Mean_CPU_Time=("CPUTimes", "mean"),
339-
)
340-
.round(3)
341-
)
342-
343-
# Combine perf_counter_df and benchmark run results on the same
344-
# "benchmark" entry.
345-
if perf_counter_df is not None:
346-
grouped_results = pd.merge(
347-
grouped_results, perf_counter_df, on="Benchmark", how="left"
348-
)
349-
350-
print(grouped_results.to_string())
351-
return grouped_results
352-
353-
def SaveBenchmarkResults(self, df: pd.DataFrame) -> None:
354-
"""Saves benchmark results to a JSON file for predictiveness analysis."""
355-
356-
file_name = os.path.join(self.temp_root, "results.json")
357-
358-
# Convert DataFrame to a list of dictionaries (one for each row)
359-
# Rename the column "Benchmark" to "Name"
360-
# TODO: This only works for open source benchmark version.
361-
362-
# We use "Benchmark" column as the index, and rename it to "name"
363-
df.index.name = "name"
364-
df = df.rename(
365-
columns={
366-
"Mean_Wall_Time": "real_time",
367-
"Mean_CPU_Time": "cpu_time",
368-
}
369-
)
370-
data = df.reset_index().to_dict(orient="records")
371-
372-
try:
373-
with open(file_name, "w") as json_file:
374-
json.dump(
375-
data, json_file, indent=4
376-
) # Serialize and write with indentation
377-
logging.info("Summary results successfully written to %s", file_name)
378-
except (IOError, json.JSONDecodeError) as e:
379-
print(f"Error writing JSON data: {e}")
380-
381312
def GeneratePerfCounterDataFrame(
382313
self, benchmark_perf_counters: str
383314
) -> pd.DataFrame | None:
@@ -461,8 +392,8 @@ def PostProcessBenchmarkResults(self, benchmark_perf_counters: str) -> None:
461392
df = self.ConvertToDataFrame()
462393

463394
perf_counter_df = self.GeneratePerfCounterDataFrame(benchmark_perf_counters)
464-
df = self.GenerateBenchmarkReport(df, perf_counter_df)
465-
self.SaveBenchmarkResults(df)
395+
df = reporter.GenerateBenchmarkReport(df, perf_counter_df)
396+
reporter.SaveBenchmarkResults(self.temp_root, df)
466397

467398
def Run(
468399
self,

fleetbench/parallel/parallel_bench_lib_test.py

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from fleetbench.parallel import benchmark as bm
2424
from fleetbench.parallel import cpu
2525
from fleetbench.parallel import parallel_bench_lib
26+
from fleetbench.parallel import reporter
2627
from fleetbench.parallel import result
2728
from fleetbench.parallel import run
2829

@@ -48,10 +49,17 @@ def tearDown(self):
4849
@mock.patch.object(bm, "GetSubBenchmarks", autospec=True)
4950
@mock.patch.object(run.Run, "Execute", autospec=True)
5051
@mock.patch.object(cpu, "Utilization", autospec=True)
52+
@mock.patch.object(reporter, "SaveBenchmarkResults", autospec=True)
5153
@flagsaver.flagsaver(
5254
benchmark_dir=absltest.get_default_test_tmpdir(),
5355
)
54-
def testRun(self, mock_utilization, mock_execute, mock_get_subbenchmarks):
56+
def testRun(
57+
self,
58+
mock_save_benchmark_results,
59+
mock_utilization,
60+
mock_execute,
61+
mock_get_subbenchmarks,
62+
):
5563
mock_get_subbenchmarks.return_value = ["BM_Test1", "BM_Test2"]
5664
mock_execute.return_value = result.Result(
5765
benchmark="fake_bench (BM_Test1)",
@@ -72,6 +80,9 @@ def fake_utilization(unused_cpus):
7280
return fake_utilizations[min(mock_utilization.call_count - 1, 1)]
7381

7482
mock_utilization.side_effect = fake_utilization
83+
84+
mock_save_benchmark_results.return_value = None
85+
7586
self.pb = parallel_bench_lib.ParallelBench(
7687
cpus=[0, 1],
7788
cpu_affinity=False,
@@ -193,57 +204,24 @@ def test_generate_perf_counter_dataframe(self):
193204
]).set_index("Benchmark")
194205
pd.testing.assert_frame_equal(df, expected_df)
195206

196-
def test_generate_benchmark_report(self):
197-
benchmark_df = pd.DataFrame([
198-
{"Benchmark": "BM_Test1", "WallTimes": 3, "CPUTimes": 3},
199-
{"Benchmark": "BM_Test2", "WallTimes": 4, "CPUTimes": 5},
200-
{"Benchmark": "BM_Test1", "WallTimes": 6, "CPUTimes": 7},
201-
])
202-
perf_counter_df = pd.DataFrame([
203-
{"Benchmark": "BM_Test1", "instructions": 130.0, "cycles": 3.0},
204-
{"Benchmark": "BM_Test2", "instructions": 200.0, "cycles": 2.0},
205-
])
206-
combined_df = self.pb.GenerateBenchmarkReport(benchmark_df, perf_counter_df)
207-
self.assertIsInstance(combined_df, pd.DataFrame)
208-
self.assertLen(combined_df, 2) # Two benchmarks: BM_Test1 and BM_Test2
209-
expected_df = pd.DataFrame([
210-
{
211-
"Benchmark": "BM_Test1",
212-
"Count": 2,
213-
"Mean_Wall_Time": 4.5,
214-
"Mean_CPU_Time": 5.0,
215-
"instructions": 130.0,
216-
"cycles": 3.0,
217-
},
218-
{
219-
"Benchmark": "BM_Test2",
220-
"Count": 1,
221-
"Mean_Wall_Time": 4,
222-
"Mean_CPU_Time": 5.0,
223-
"instructions": 200.0,
224-
"cycles": 2.0,
225-
},
207+
@mock.patch.object(reporter, "SaveBenchmarkResults", autospec=True)
208+
@mock.patch.object(reporter, "GenerateBenchmarkReport", autospec=True)
209+
@mock.patch.object(
210+
parallel_bench_lib.ParallelBench, "ConvertToDataFrame", autospec=True
211+
)
212+
def test_post_processing_benchmark_results(
213+
self,
214+
mock_convert_to_dataframe,
215+
mock_generate_benchmark_report,
216+
mock_save_benchmark_results,
217+
):
218+
mock_convert_to_dataframe.return_value = pd.DataFrame([
219+
{"Benchmark": "test_benchmark1", "WallTimes": 10, "CPUTimes": 10},
226220
])
227-
pd.testing.assert_frame_equal(combined_df, expected_df)
228221

229-
def test_save_benchmark_results(self):
230-
df = pd.DataFrame([
231-
{"Benchmark": "BM_Test1", "Mean_Wall_Time": 1, "Mean_CPU_Time": 1},
232-
{"Benchmark": "BM_Test2", "Mean_Wall_Time": 1, "Mean_CPU_Time": 2},
233-
]).set_index("Benchmark")
234-
235-
self.pb.SaveBenchmarkResults(df)
236-
file_name = os.path.join(absltest.get_default_test_tmpdir(), "results.json")
237-
self.assertTrue(os.path.exists(file_name))
238-
with open(file_name, "r") as json_file:
239-
data = json.load(json_file)
240-
self.assertEqual(
241-
data,
242-
[
243-
{"name": "BM_Test1", "real_time": 1, "cpu_time": 1},
244-
{"name": "BM_Test2", "real_time": 1, "cpu_time": 2},
245-
],
246-
)
222+
self.pb.PostProcessBenchmarkResults("instructions,cycles")
223+
mock_generate_benchmark_report.assert_called_once()
224+
mock_save_benchmark_results.assert_called_once()
247225

248226

249227
class ParseBenchmarkWeightsTest(absltest.TestCase):

0 commit comments

Comments
 (0)