Skip to content

Commit 6ae4d8c

Browse files
committed
Use Google Benchmark for performance tables
1 parent c358e80 commit 6ae4d8c

27 files changed

Lines changed: 949 additions & 895 deletions

File tree

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ indent_size = 2
1717
[*.py]
1818
indent_size = 4
1919

20+
[*.{bat,cmd}]
21+
end_of_line = crlf
22+
2023
[Makefile]
2124
indent_style = tab
2225

.github/workflows/perf.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
tar -xzvf ubuntu-gcc-install-ubuntu-24.04.tar.gz -C install
3131
- name: Run perf tests
3232
run: |
33-
bash -e scripts/generate_perf_results.sh
33+
scripts/run_tests.py --running-type=performance
3434
env:
3535
PPC_NUM_PROC: 2
3636
PPC_NUM_THREADS: 2
@@ -68,7 +68,7 @@ jobs:
6868
tar -xzvf macos-clang-install.tar.gz -C install
6969
- name: Run perf tests
7070
run: |
71-
bash -e scripts/generate_perf_results.sh
71+
scripts/run_tests.py --running-type=performance
7272
env:
7373
PPC_NUM_PROC: 1
7474
PPC_NUM_THREADS: 2

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
[submodule "3rdparty/libenvpp"]
1414
path = 3rdparty/libenvpp
1515
url = https://github.com/ph3at/libenvpp
16+
[submodule "3rdparty/benchmark"]
17+
path = 3rdparty/benchmark
18+
url = https://github.com/google/benchmark

3rdparty/benchmark

Submodule benchmark added at a846068

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ endforeach()
4444

4545
message( STATUS "PPC step: Setup external projects" )
4646
include(cmake/gtest.cmake)
47+
include(cmake/benchmark.cmake)
4748

4849
############################## Modules ##############################
4950

cmake/benchmark.cmake

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
include_guard()
2+
3+
include(ExternalProject)
4+
5+
ExternalProject_Add(
6+
ppc_benchmark
7+
SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/benchmark"
8+
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark"
9+
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark/build"
10+
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark/install"
11+
EXCLUDE_FROM_ALL TRUE
12+
CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
13+
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
14+
-DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}
15+
-DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER}
16+
-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
17+
-DCMAKE_CXX_STANDARD_REQUIRED=${CMAKE_CXX_STANDARD_REQUIRED}
18+
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
19+
${PPC_EXTERNAL_PROJECT_CMAKE_ARGS}
20+
-DCMAKE_C_FLAGS=-w
21+
-DCMAKE_CXX_FLAGS=-w
22+
-DBENCHMARK_ENABLE_TESTING=OFF
23+
-DBENCHMARK_ENABLE_GTEST_TESTS=OFF
24+
-DBENCHMARK_ENABLE_WERROR=OFF
25+
-DBENCHMARK_ENABLE_INSTALL=ON
26+
-DBENCHMARK_ENABLE_LIBPFM=OFF
27+
BUILD_COMMAND
28+
"${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark/build"
29+
--config $<CONFIG> --parallel
30+
INSTALL_COMMAND
31+
"${CMAKE_COMMAND}" --install
32+
"${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark/build" --config $<CONFIG>
33+
--prefix "${CMAKE_CURRENT_BINARY_DIR}/ppc_benchmark/install"
34+
${PPC_EXTERNAL_PROJECT_LOG_ARGS})
35+
36+
function(ppc_include_benchmark target_name)
37+
target_include_directories(
38+
${target_name} PUBLIC ${CMAKE_SOURCE_DIR}/3rdparty/benchmark/include)
39+
target_compile_definitions(${target_name} PUBLIC BENCHMARK_STATIC_DEFINE)
40+
endfunction()
41+
42+
function(ppc_link_benchmark target_name)
43+
ppc_include_benchmark(${target_name})
44+
add_dependencies(${target_name} ppc_benchmark)
45+
target_link_directories(${target_name} PUBLIC
46+
"${CMAKE_BINARY_DIR}/ppc_benchmark/install/lib")
47+
target_link_libraries(${target_name} PUBLIC benchmark Threads::Threads)
48+
if(WIN32)
49+
target_link_libraries(${target_name} PUBLIC shlwapi)
50+
endif()
51+
endfunction()

modules/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ set_target_properties(${exec_func_lib} PROPERTIES LINKER_LANGUAGE CXX)
2626
target_include_directories(
2727
${exec_func_lib} PUBLIC ${CMAKE_SOURCE_DIR}/3rdparty
2828
${CMAKE_SOURCE_DIR}/modules ${CMAKE_SOURCE_DIR}/tasks)
29+
ppc_include_benchmark(${exec_func_lib})
2930

3031
foreach(
3132
link

modules/performance/include/performance.hpp

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <iomanip>
66
#include <iostream>
77
#include <memory>
8-
#include <sstream>
98
#include <stdexcept>
109
#include <string>
1110

@@ -30,6 +29,7 @@ struct PerfAttr {
3029
struct PerfResults {
3130
/// @brief Measured execution time in seconds.
3231
double time_sec = 0.0;
32+
bool is_measured = false;
3333
enum class TypeOfRunning : uint8_t {
3434
kPipeline,
3535
kTaskRun,
@@ -39,18 +39,26 @@ struct PerfResults {
3939
constexpr static double kMaxTime = 10.0;
4040
};
4141

42+
inline std::string GetStringParamName(PerfResults::TypeOfRunning type_of_running) {
43+
if (type_of_running == PerfResults::TypeOfRunning::kTaskRun) {
44+
return "task_run";
45+
}
46+
if (type_of_running == PerfResults::TypeOfRunning::kPipeline) {
47+
return "pipeline";
48+
}
49+
return "none";
50+
}
51+
4252
template <typename InType, typename OutType>
4353
class Perf {
4454
public:
4555
// Init performance analysis with an initialized task and initialized data
4656
explicit Perf(const ppc::task::TaskPtr<InType, OutType> &task_ptr) : task_(task_ptr) {
4757
task_ptr->GetStateOfTesting() = ppc::task::StateOfTesting::kPerf;
4858
}
49-
// Check performance of full task's pipeline: PreProcessing() ->
50-
// Validation() -> Run() -> PostProcessing()
59+
// Check performance of the full task pipeline. Kept for source compatibility with older student tests.
5160
void PipelineRun(const PerfAttr &perf_attr) {
5261
perf_results_.type_of_running = PerfResults::TypeOfRunning::kPipeline;
53-
5462
CommonRun(perf_attr, [&] {
5563
task_->Validation();
5664
task_->PreProcessing();
@@ -61,7 +69,6 @@ class Perf {
6169
// Check performance of task's Run() function
6270
void TaskRun(const PerfAttr &perf_attr) {
6371
perf_results_.type_of_running = PerfResults::TypeOfRunning::kTaskRun;
64-
6572
task_->Validation();
6673
task_->PreProcessing();
6774
CommonRun(perf_attr, [&] { task_->Run(); }, perf_results_);
@@ -74,31 +81,21 @@ class Perf {
7481
}
7582
// Print results for automation checkers
7683
void PrintPerfStatistic(const std::string &test_id) const {
77-
std::string type_test_name;
78-
if (perf_results_.type_of_running == PerfResults::TypeOfRunning::kTaskRun) {
79-
type_test_name = "task_run";
80-
} else if (perf_results_.type_of_running == PerfResults::TypeOfRunning::kPipeline) {
81-
type_test_name = "pipeline";
82-
} else {
83-
std::stringstream err_msg;
84-
err_msg << '\n' << "The type of performance check for the task was not selected.\n";
85-
throw std::runtime_error(err_msg.str().c_str());
84+
if (!perf_results_.is_measured) {
85+
throw std::runtime_error("Performance measurement was not run.");
86+
}
87+
if (perf_results_.type_of_running == PerfResults::TypeOfRunning::kNone) {
88+
throw std::runtime_error("The type of performance check for the task was not selected.");
8689
}
8790

8891
auto time_secs = perf_results_.time_sec;
8992
const auto max_time = ppc::util::GetPerfMaxTime();
90-
std::stringstream perf_res_str;
93+
const auto type_test_name = GetStringParamName(perf_results_.type_of_running);
9194
if (time_secs < max_time) {
92-
perf_res_str << std::fixed << std::setprecision(10) << time_secs;
93-
std::cout << test_id << ":" << type_test_name << ":" << perf_res_str.str() << '\n';
95+
std::cout << test_id << ':' << type_test_name << ':' << std::fixed << std::setprecision(10) << time_secs << '\n';
9496
} else {
95-
std::stringstream err_msg;
96-
err_msg << '\n' << "Task execute time need to be: ";
97-
err_msg << "time < " << max_time << " secs." << '\n';
98-
err_msg << "Original time in secs: " << time_secs << '\n';
99-
perf_res_str << std::fixed << std::setprecision(10) << -1.0;
100-
std::cout << test_id << ":" << type_test_name << ":" << perf_res_str.str() << '\n';
101-
throw std::runtime_error(err_msg.str().c_str());
97+
std::cout << test_id << ':' << type_test_name << ':' << std::fixed << std::setprecision(10) << -1.0 << '\n';
98+
throw std::runtime_error("Task execution time exceeded the performance limit.");
10299
}
103100
}
104101
/// @brief Retrieves the performance test results.
@@ -110,24 +107,15 @@ class Perf {
110107
private:
111108
PerfResults perf_results_;
112109
std::shared_ptr<ppc::task::Task<InType, OutType>> task_;
113-
static void CommonRun(const PerfAttr &perf_attr, const std::function<void()> &pipeline, PerfResults &perf_results) {
110+
static void CommonRun(const PerfAttr &perf_attr, const std::function<void()> &operation, PerfResults &perf_results) {
114111
auto begin = perf_attr.current_timer();
115112
for (uint64_t i = 0; i < perf_attr.num_running; i++) {
116-
pipeline();
113+
operation();
117114
}
118115
auto end = perf_attr.current_timer();
119116
perf_results.time_sec = (end - begin) / static_cast<double>(perf_attr.num_running);
117+
perf_results.is_measured = true;
120118
}
121119
};
122120

123-
inline std::string GetStringParamName(PerfResults::TypeOfRunning type_of_running) {
124-
if (type_of_running == PerfResults::TypeOfRunning::kTaskRun) {
125-
return "task_run";
126-
}
127-
if (type_of_running == PerfResults::TypeOfRunning::kPipeline) {
128-
return "pipeline";
129-
}
130-
return "none";
131-
}
132-
133121
} // namespace ppc::performance

modules/performance/tests/perf_tests.cpp

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -68,37 +68,37 @@ class FakePerfTask : public TestPerfTask<InType, OutType> {
6868

6969
namespace ppc::performance {
7070

71-
TEST(PerfTests, CheckPerfPipeline) {
71+
TEST(PerfTests, CheckPerfTaskRun) {
7272
std::vector<uint32_t> in(2000, 1);
7373

7474
auto test_task = std::make_shared<ppc::test::TestPerfTask<std::vector<uint32_t>, uint32_t>>(in);
7575

7676
Perf<std::vector<uint32_t>, uint32_t> perf_analyzer(test_task);
7777

7878
PerfAttr perf_attr;
79-
perf_analyzer.PipelineRun(perf_attr);
79+
perf_analyzer.TaskRun(perf_attr);
8080

81-
perf_analyzer.PrintPerfStatistic("check_perf_pipeline");
81+
perf_analyzer.PrintPerfStatistic("check_perf");
8282
ASSERT_LE(perf_analyzer.GetPerfResults().time_sec, PerfResults::kMaxTime);
8383
EXPECT_EQ(test_task->GetOutput(), in.size());
8484
}
8585

86-
TEST(PerfTests, CheckPerfPipelineFloat) {
86+
TEST(PerfTests, CheckPerfTaskRunFloat) {
8787
std::vector<float> in(2000, 1);
8888

8989
auto test_task = std::make_shared<ppc::test::TestPerfTask<std::vector<float>, float>>(in);
9090

9191
Perf<std::vector<float>, float> perf_analyzer(test_task);
9292

9393
PerfAttr perf_attr;
94-
perf_analyzer.PipelineRun(perf_attr);
94+
perf_analyzer.TaskRun(perf_attr);
9595

96-
perf_analyzer.PrintPerfStatistic("check_perf_pipeline_float");
96+
perf_analyzer.PrintPerfStatistic("check_perf_float");
9797
ASSERT_LE(perf_analyzer.GetPerfResults().time_sec, PerfResults::kMaxTime);
9898
EXPECT_EQ(test_task->GetOutput(), in.size());
9999
}
100100

101-
TEST(PerfTests, CheckPerfPipelineUint8tSlowTest) {
101+
TEST(PerfTests, CheckPerfUint8tSlowTest) {
102102
std::vector<uint8_t> in(128, 1);
103103

104104
auto test_task = std::make_shared<ppc::test::FakePerfTask<std::vector<uint8_t>, uint8_t>>(in);
@@ -114,9 +114,9 @@ TEST(PerfTests, CheckPerfPipelineUint8tSlowTest) {
114114
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time_point - t0).count();
115115
return static_cast<double>(duration) * 1e-9;
116116
};
117-
perf_analyzer.PipelineRun(perf_attr);
117+
perf_analyzer.TaskRun(perf_attr);
118118

119-
ASSERT_ANY_THROW(perf_analyzer.PrintPerfStatistic("check_perf_pipeline_uint8_t_slow_test"));
119+
ASSERT_ANY_THROW(perf_analyzer.PrintPerfStatistic("check_perf_uint8_t_slow_test"));
120120
}
121121

122122
TEST(PerfTests, SlowPerfRespectsEnvOverride) {
@@ -132,7 +132,7 @@ TEST(PerfTests, SlowPerfRespectsEnvOverride) {
132132
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time_point - t0).count();
133133
return static_cast<double>(duration) * 1e-9;
134134
};
135-
perf_analyzer.PipelineRun(perf_attr);
135+
perf_analyzer.TaskRun(perf_attr);
136136
EXPECT_NO_THROW(perf_analyzer.PrintPerfStatistic("slow_perf_respects_env_override"));
137137
}
138138

@@ -164,26 +164,6 @@ TEST(PerfTests, CheckPerfTaskFloat) {
164164
EXPECT_EQ(test_task->GetOutput(), in.size());
165165
}
166166

167-
struct ParamTestCase {
168-
PerfResults::TypeOfRunning input;
169-
std::string_view expected_output;
170-
};
171-
172-
namespace {
173-
174-
constexpr std::array<ParamTestCase, 3> kParamTestCases = {
175-
{{.input = PerfResults::TypeOfRunning::kTaskRun, .expected_output = "task_run"},
176-
{.input = PerfResults::TypeOfRunning::kPipeline, .expected_output = "pipeline"},
177-
{.input = PerfResults::TypeOfRunning::kNone, .expected_output = "none"}}};
178-
179-
} // namespace
180-
181-
TEST(GetStringParamNameParamTest, ReturnsExpectedString) {
182-
for (const auto &param : kParamTestCases) {
183-
EXPECT_EQ(GetStringParamName(param.input), std::string(param.expected_output));
184-
}
185-
}
186-
187167
struct TaskTypeTestCase {
188168
TypeOfTask type;
189169
std::string_view expected;
@@ -336,7 +316,7 @@ TEST(GetNamespaceTest, ReturnsEmptyStringForGlobalNamespaceType) {
336316
EXPECT_EQ(ppc::util::GetNamespace<int>(), "");
337317
}
338318

339-
TEST(PerfTest, PipelineRunAndTaskRun) {
319+
TEST(PerfTest, TaskRunMeasuresExecutionTime) {
340320
auto task_ptr = std::make_shared<DummyTask>();
341321
Perf<int, int> perf(task_ptr);
342322

@@ -349,15 +329,31 @@ TEST(PerfTest, PipelineRunAndTaskRun) {
349329
return t;
350330
};
351331

352-
EXPECT_NO_THROW(perf.PipelineRun(attr));
353-
auto res_pipeline = perf.GetPerfResults();
354-
EXPECT_EQ(res_pipeline.type_of_running, PerfResults::TypeOfRunning::kPipeline);
355-
EXPECT_GT(res_pipeline.time_sec, 0.0);
356-
357332
EXPECT_NO_THROW(perf.TaskRun(attr));
358-
auto res_taskrun = perf.GetPerfResults();
359-
EXPECT_EQ(res_taskrun.type_of_running, PerfResults::TypeOfRunning::kTaskRun);
360-
EXPECT_GT(res_taskrun.time_sec, 0.0);
333+
auto result = perf.GetPerfResults();
334+
EXPECT_TRUE(result.is_measured);
335+
EXPECT_GT(result.time_sec, 0.0);
336+
}
337+
338+
TEST(PerfTest, PipelineRunCompatibilityApiMeasuresExecutionTime) {
339+
auto task_ptr = std::make_shared<DummyTask>();
340+
Perf<int, int> perf(task_ptr);
341+
342+
PerfAttr attr;
343+
double time = 0.0;
344+
attr.num_running = 2;
345+
attr.current_timer = [&time]() {
346+
double t = time;
347+
time += 1.0;
348+
return t;
349+
};
350+
351+
perf.PipelineRun(attr);
352+
auto result = perf.GetPerfResults();
353+
EXPECT_TRUE(result.is_measured);
354+
EXPECT_EQ(result.type_of_running, PerfResults::TypeOfRunning::kPipeline);
355+
EXPECT_GT(result.time_sec, 0.0);
356+
EXPECT_EQ(GetStringParamName(result.type_of_running), "pipeline");
361357
}
362358

363359
TEST(PerfTest, PrintPerfStatisticThrowsOnNone) {
@@ -370,12 +366,6 @@ TEST(PerfTest, PrintPerfStatisticThrowsOnNone) {
370366
ppc::util::DestructorFailureFlag::Unset();
371367
}
372368

373-
TEST(PerfTest, GetStringParamNameTest) {
374-
EXPECT_EQ(GetStringParamName(PerfResults::TypeOfRunning::kTaskRun), "task_run");
375-
EXPECT_EQ(GetStringParamName(PerfResults::TypeOfRunning::kPipeline), "pipeline");
376-
EXPECT_EQ(GetStringParamName(PerfResults::TypeOfRunning::kNone), "none");
377-
}
378-
379369
TEST(TaskTest, DestructorInvalidPipelineOrderTerminatesPartialPipeline) {
380370
{
381371
struct BadTask : Task<int, int> {

0 commit comments

Comments
 (0)