From d07d3d8a70acd9f9414167ee6f48a6a355d090c2 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Wed, 22 Dec 2021 13:23:46 +0100 Subject: [PATCH 1/6] gtest: Start work on new test infrastructure Use GTest to run tests. This should help us in quite a few places. Signed-off-by: Johannes Demel --- CMakeLists.txt | 5 ++ tests/CMakeLists.txt | 54 +++++++++++++++++++ tests/test_volk_32fc_x2_multiply_32fc.cc | 66 ++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/test_volk_32fc_x2_multiply_32fc.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 01f0acb31..f91f88af3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -371,6 +371,11 @@ message(STATUS " Modify using: -DENABLE_PROFILING=ON/OFF") ######################################################################## add_subdirectory(lib) +######################################################################## +# Add tests +######################################################################## +add_subdirectory(tests) + ######################################################################## # And the utility apps ######################################################################## diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..da0adbc40 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# Copyright 2021 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +add_subdirectory(googletest) + +add_executable( + volk_tests + test_volk_32fc_x2_multiply_32fc.cc +) +target_link_libraries( + volk_tests + gtest_main + volk +) + +include(GoogleTest) +gtest_discover_tests(volk_tests) + + +target_include_directories(volk_tests + PRIVATE $ + PRIVATE $ + PRIVATE $ + PRIVATE $ + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} +) + +# if(ENABLE_STATIC_LIBS) +# target_link_libraries(volk_tests PRIVATE volk_static) +# set_target_properties(volk_tests PROPERTIES LINK_FLAGS "-static") +# else() +# target_link_libraries(volk_tests PRIVATE volk) +# endif() + +# install( +# TARGETS volk_tests +# DESTINATION bin +# COMPONENT "volk" +# ) \ No newline at end of file diff --git a/tests/test_volk_32fc_x2_multiply_32fc.cc b/tests/test_volk_32fc_x2_multiply_32fc.cc new file mode 100644 index 000000000..fab99310f --- /dev/null +++ b/tests/test_volk_32fc_x2_multiply_32fc.cc @@ -0,0 +1,66 @@ +#include +#include +#include + + +template +::testing::AssertionResult AreComplexFloatingPointArraysAlmostEqual(const T& expected, + const T& actual) +{ + ::testing::AssertionResult result = ::testing::AssertionFailure(); + if (expected.size() != actual.size()) { + return result << "expected result size=" << expected.size() + << " differs from actual size=" << actual.size(); + } + const unsigned long length = expected.size(); + + int errorsFound = 0; + const char* separator = " "; + for (unsigned long index = 0; index < length; index++) { + auto expected_real = ::testing::internal::FloatingPoint(expected[index].real()); + auto expected_imag = ::testing::internal::FloatingPoint(expected[index].imag()); + auto actual_real = ::testing::internal::FloatingPoint(actual[index].real()); + auto actual_imag = ::testing::internal::FloatingPoint(actual[index].imag()); + if (not expected_real.AlmostEquals(actual_real) or + not expected_imag.AlmostEquals(actual_imag)) + + { + if (errorsFound == 0) { + result << "Differences found:"; + } + if (errorsFound < 3) { + result << separator << expected[index] << " != " << actual[index] << " @ " + << index; + separator = ",\n"; + } + errorsFound++; + } + } + if (errorsFound > 0) { + result << separator << errorsFound << " differences in total"; + return result; + } + return ::testing::AssertionSuccess(); +} + + +TEST(Multiply, AVX) +{ + const size_t vector_length = 32; + auto vec0 = volk::vector(vector_length); + auto vec1 = volk::vector(vector_length); + auto result = volk::vector(vector_length); + for (size_t i = 0; i < vector_length; ++i) { + vec0[i] = std::complex(i * 3.14, i * 0.45); + vec1[i] = std::complex(i * -2.78, i * 5.44); + } + + auto expected = volk::vector(vector_length); + for (size_t i = 0; i < vector_length; ++i) { + expected[i] = vec0[i] * vec1[i]; + } + + volk_32fc_x2_multiply_32fc_manual(result.data(), vec0.data(), vec1.data(), vector_length); + // EXPECT_ITERABLE_COMPLEX_FLOAT_EQ(volk::vector, expected, result); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); +} From 2f6eb4c1fea1008a4c31871c3bf124990b913e3d Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Sat, 19 Nov 2022 19:52:39 +0100 Subject: [PATCH 2/6] ci: Add a second test example This is an ongoing effort to introduce some more sophisticated QA tests. We use googletest and write custom test suits. This approach requires more manual work but yields a more accurate result as well. Signed-off-by: Johannes Demel --- tests/CMakeLists.txt | 24 ++-- tests/test_volk_32f_x3_sum_of_poly_32f.cc | 141 ++++++++++++++++++++++ tests/test_volk_32fc_x2_multiply_32fc.cc | 141 ++++++++++++++-------- tests/volk_test.cc | 80 ++++++++++++ tests/volk_test.h | 76 ++++++++++++ tmpl/volk.tmpl.c | 9 +- 6 files changed, 407 insertions(+), 64 deletions(-) create mode 100644 tests/test_volk_32f_x3_sum_of_poly_32f.cc create mode 100644 tests/volk_test.cc create mode 100644 tests/volk_test.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index da0adbc40..860adb74f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,30 +1,28 @@ # -# Copyright 2021 Free Software Foundation, Inc. +# Copyright 2022, 2024 Johannes Demel # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# This file is part of VOLK. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# SPDX-License-Identifier: LGPL-3.0-or-later # add_subdirectory(googletest) +find_package(fmt REQUIRED) + +file(GLOB volk_test_files "test_*.cc") + add_executable( volk_tests - test_volk_32fc_x2_multiply_32fc.cc + volk_test.cc + ${volk_test_files} ) + target_link_libraries( volk_tests gtest_main volk + fmt::fmt ) include(GoogleTest) diff --git a/tests/test_volk_32f_x3_sum_of_poly_32f.cc b/tests/test_volk_32f_x3_sum_of_poly_32f.cc new file mode 100644 index 000000000..59c50ebfb --- /dev/null +++ b/tests/test_volk_32f_x3_sum_of_poly_32f.cc @@ -0,0 +1,141 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "volk_test.h" +#include +#include +#include +#include +#include +#include +#include + + +class volk_32f_x3_sum_of_poly_32f_test : public VolkTest +{ +protected: + void SetUp() override + { + initialize_implementation_names(volk_32f_x3_sum_of_poly_32f_get_func_desc()); + initialize_data(GetParam()); + } + + void initialize_data(const size_t length) + { + vector_length = length; + + vec0 = volk::vector(length); + for (size_t i = 0; i < length; ++i) { + vec0[i] = float(2.8f + i * 0.14f); + } + + ua_vec0 = volk::vector({ 0.0f }); + for (auto v : vec0) { + ua_vec0.push_back(v); + } + + center_points = volk::vector({ 4.4, 2.1, 0.3, 0.05, 4.1 }); + ua_center_points = volk::vector({ + 0.0, + }); + for (auto v : center_points) { + ua_center_points.push_back(v); + } + + cutoff = volk::vector({ -1.5 }); + ua_cutoff = cutoff; + ua_cutoff.push_back(cutoff.at(0)); + + expected = 0.0f; + for (auto value : vec0) { + value = std::max(value, cutoff.at(0)); + auto sq = value * value; + auto cube = sq * value; + auto quartic = value * cube; + expected += value * center_points[0] + sq * center_points[1] + + cube * center_points[2] + quartic * center_points[3]; + } + expected += center_points[4] * float(length); + + result = volk::vector(1, 0.0); + ua_result.push_back(result.at(0)); + ua_result.push_back(result.at(0)); + } + + void execute_aligned(const std::string impl_name) + { + volk_32f_x3_sum_of_poly_32f_manual(result.data(), + vec0.data(), + center_points.data(), + cutoff.data(), + vector_length, + impl_name.c_str()); + } + + void execute_unaligned(const std::string impl_name) + { + volk_32f_x3_sum_of_poly_32f_manual(ua_result.data() + 1, + ua_vec0.data() + 1, + ua_center_points.data() + 1, + ua_cutoff.data() + 1, + vector_length, + impl_name.c_str()); + } + + // void TearDown() override {} + size_t vector_length; + volk::vector vec0; + volk::vector ua_vec0; + volk::vector center_points; + volk::vector ua_center_points; + volk::vector cutoff; + volk::vector ua_cutoff; + volk::vector result; + volk::vector ua_result; + float expected = 0.0f; +}; + + +TEST_P(volk_32f_x3_sum_of_poly_32f_test, aligned) +{ + for (auto name : implementation_names) { + auto tol = std::max(expected * 1e-5, 1e-5); + fmt::print( + "test aligned implementation: {:>12}, size={} ...", name, vector_length); + auto start = std::chrono::steady_clock::now(); + + execute_aligned(name); + + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); + EXPECT_NEAR(result.at(0), expected, tol); + } +} + +TEST_P(volk_32f_x3_sum_of_poly_32f_test, unaligned) +{ + for (auto name : unaligned_impl_names) { + auto tol = std::max(expected * 1e-5, 1e-5); + fmt::print( + "test unaligned implementation: {:>12}, size={} ...", name, vector_length); + auto start = std::chrono::steady_clock::now(); + + execute_unaligned(name); + + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); + EXPECT_NEAR(ua_result.at(1), expected, tol); + } +} + + +INSTANTIATE_TEST_SUITE_P(volk_32f_x3_sum_of_poly_32f, + volk_32f_x3_sum_of_poly_32f_test, + // testing::Values(8, 32) + testing::Values(7, 32, 128, 1023, 65535, 131071)); diff --git a/tests/test_volk_32fc_x2_multiply_32fc.cc b/tests/test_volk_32fc_x2_multiply_32fc.cc index fab99310f..77daebebb 100644 --- a/tests/test_volk_32fc_x2_multiply_32fc.cc +++ b/tests/test_volk_32fc_x2_multiply_32fc.cc @@ -1,66 +1,109 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "volk_test.h" +#include +#include +#include #include #include #include +#include -template -::testing::AssertionResult AreComplexFloatingPointArraysAlmostEqual(const T& expected, - const T& actual) +class volk_32fc_x2_multiply_32fc_test : public VolkTest { - ::testing::AssertionResult result = ::testing::AssertionFailure(); - if (expected.size() != actual.size()) { - return result << "expected result size=" << expected.size() - << " differs from actual size=" << actual.size(); +protected: + void SetUp() override + { + initialize_implementation_names(volk_32fc_x2_multiply_32fc_get_func_desc()); + initialize_data(GetParam()); } - const unsigned long length = expected.size(); - - int errorsFound = 0; - const char* separator = " "; - for (unsigned long index = 0; index < length; index++) { - auto expected_real = ::testing::internal::FloatingPoint(expected[index].real()); - auto expected_imag = ::testing::internal::FloatingPoint(expected[index].imag()); - auto actual_real = ::testing::internal::FloatingPoint(actual[index].real()); - auto actual_imag = ::testing::internal::FloatingPoint(actual[index].imag()); - if (not expected_real.AlmostEquals(actual_real) or - not expected_imag.AlmostEquals(actual_imag)) - - { - if (errorsFound == 0) { - result << "Differences found:"; - } - if (errorsFound < 3) { - result << separator << expected[index] << " != " << actual[index] << " @ " - << index; - separator = ",\n"; - } - errorsFound++; + + void initialize_data(const size_t length) + { + vector_length = length; + vec0 = volk::vector(length); + vec1 = volk::vector(length); + result = volk::vector(length); + for (size_t i = 0; i < length; ++i) { + vec0[i] = std::complex(i * 3.14, i * 0.45); + vec1[i] = std::complex(i * -2.78, i * 5.44); } + + expected = volk::vector(length); + for (size_t i = 0; i < length; ++i) { + expected[i] = vec0[i] * vec1[i]; + } + + // This is a hacky solution to have unaligned tests. + ua_result = result; + ua_result.at(0) = expected.at(0); } - if (errorsFound > 0) { - result << separator << errorsFound << " differences in total"; - return result; + + void execute_aligned(const std::string impl_name) + { + volk_32fc_x2_multiply_32fc_manual( + result.data(), vec0.data(), vec1.data(), vector_length, impl_name.c_str()); } - return ::testing::AssertionSuccess(); -} + void execute_unaligned(const std::string impl_name) + { + volk_32fc_x2_multiply_32fc_manual(ua_result.data() + 1, + vec0.data() + 1, + vec1.data() + 1, + vector_length - 1, + impl_name.c_str()); + } + + // void TearDown() override {} + size_t vector_length; + volk::vector vec0; + volk::vector vec1; + volk::vector result; + volk::vector expected; + + volk::vector ua_result; +}; -TEST(Multiply, AVX) + +TEST_P(volk_32fc_x2_multiply_32fc_test, aligned) { - const size_t vector_length = 32; - auto vec0 = volk::vector(vector_length); - auto vec1 = volk::vector(vector_length); - auto result = volk::vector(vector_length); - for (size_t i = 0; i < vector_length; ++i) { - vec0[i] = std::complex(i * 3.14, i * 0.45); - vec1[i] = std::complex(i * -2.78, i * 5.44); - } + for (auto name : implementation_names) { + fmt::print( + "test aligned implementation: {:>12}, size={} ...", name, vector_length); + auto start = std::chrono::steady_clock::now(); + + execute_aligned(name); - auto expected = volk::vector(vector_length); - for (size_t i = 0; i < vector_length; ++i) { - expected[i] = vec0[i] * vec1[i]; + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); } +} + +TEST_P(volk_32fc_x2_multiply_32fc_test, unaligned) +{ + for (auto name : unaligned_impl_names) { + fmt::print( + "test unaligned implementation: {:>12}, size={} ...", name, vector_length); + auto start = std::chrono::steady_clock::now(); + + execute_unaligned(name); - volk_32fc_x2_multiply_32fc_manual(result.data(), vec0.data(), vec1.data(), vector_length); - // EXPECT_ITERABLE_COMPLEX_FLOAT_EQ(volk::vector, expected, result); - EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, ua_result)); + } } + + +INSTANTIATE_TEST_SUITE_P(volk_32fc_x2_multiply_32fc, + volk_32fc_x2_multiply_32fc_test, + testing::Values(7, 32, 128, 1023, 131071)); diff --git a/tests/volk_test.cc b/tests/volk_test.cc new file mode 100644 index 000000000..ac580b40d --- /dev/null +++ b/tests/volk_test.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include +#include +#include +#include +#include + + +template +::testing::AssertionResult AreComplexFloatingPointArraysAlmostEqual(const T& expected, + const T& actual) +{ + ::testing::AssertionResult result = ::testing::AssertionFailure(); + if (expected.size() != actual.size()) { + return result << "expected result size=" << expected.size() + << " differs from actual size=" << actual.size(); + } + const unsigned long length = expected.size(); + + int errorsFound = 0; + const char* separator = " "; + for (unsigned long index = 0; index < length; index++) { + auto expected_real = ::testing::internal::FloatingPoint(expected[index].real()); + auto expected_imag = ::testing::internal::FloatingPoint(expected[index].imag()); + auto actual_real = ::testing::internal::FloatingPoint(actual[index].real()); + auto actual_imag = ::testing::internal::FloatingPoint(actual[index].imag()); + if (not expected_real.AlmostEquals(actual_real) or + not expected_imag.AlmostEquals(actual_imag)) + + { + if (errorsFound == 0) { + result << "Differences found:"; + } + if (errorsFound < 3) { + result << separator << expected[index] << " != " << actual[index] << " @ " + << index; + separator = ",\n"; + } + errorsFound++; + } + } + if (errorsFound > 0) { + result << separator << errorsFound << " differences in total"; + return result; + } + return ::testing::AssertionSuccess(); +} + +std::vector get_kernel_implementation_name_list(volk_func_desc_t desc) +{ + std::vector names; + for (size_t i = 0; i < desc.n_impls; i++) { + names.push_back(std::string(desc.impl_names[i])); + } + std::sort(names.begin(), names.end()); + return names; +} + +std::tuple, std::vector> +separate_implementations_by_alignment(std::vector names) +{ + std::vector aligned; + std::vector unaligned; + for (auto name : names) { + if (name.rfind("a_", 0) == 0) { + aligned.push_back(name); + } else { + unaligned.push_back(name); + } + } + return { aligned, unaligned }; +} diff --git a/tests/volk_test.h b/tests/volk_test.h new file mode 100644 index 000000000..20f8780bb --- /dev/null +++ b/tests/volk_test.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include +#include +#include +#include +#include + + +std::vector get_kernel_implementation_name_list(volk_func_desc_t desc); + +std::tuple, std::vector> +separate_implementations_by_alignment(std::vector names); + +class VolkTest : public ::testing::TestWithParam +{ +protected: + void initialize_implementation_names(volk_func_desc_t desc) + { + implementation_names = get_kernel_implementation_name_list(desc); + std::tie(aligned_impl_names, unaligned_impl_names) = + separate_implementations_by_alignment(implementation_names); + } + + std::vector implementation_names; + std::vector aligned_impl_names; + std::vector unaligned_impl_names; +}; + + +template +::testing::AssertionResult AreComplexFloatingPointArraysAlmostEqual(const T& expected, + const T& actual) +{ + ::testing::AssertionResult result = ::testing::AssertionFailure(); + if (expected.size() != actual.size()) { + return result << "expected result size=" << expected.size() + << " differs from actual size=" << actual.size(); + } + const unsigned long length = expected.size(); + + int errorsFound = 0; + const char* separator = " "; + for (unsigned long index = 0; index < length; index++) { + auto expected_real = ::testing::internal::FloatingPoint(expected[index].real()); + auto expected_imag = ::testing::internal::FloatingPoint(expected[index].imag()); + auto actual_real = ::testing::internal::FloatingPoint(actual[index].real()); + auto actual_imag = ::testing::internal::FloatingPoint(actual[index].imag()); + if (not expected_real.AlmostEquals(actual_real) or + not expected_imag.AlmostEquals(actual_imag)) + + { + if (errorsFound == 0) { + result << "Differences found:"; + } + if (errorsFound < 3) { + result << separator << expected[index] << " != " << actual[index] << " @ " + << index; + separator = ",\n"; + } + errorsFound++; + } + } + if (errorsFound > 0) { + result << separator << errorsFound << " differences in total"; + return result; + } + return ::testing::AssertionSuccess(); +} diff --git a/tmpl/volk.tmpl.c b/tmpl/volk.tmpl.c index 62a9400ad..63c52b92c 100644 --- a/tmpl/volk.tmpl.c +++ b/tmpl/volk.tmpl.c @@ -169,14 +169,19 @@ static inline void __${kern.name}(${kern.arglist_full}) ${kern.pname} ${kern.name}_u = &__${kern.name}_u; ${kern.pname} ${kern.name} = &__${kern.name}; -void ${kern.name}_manual(${kern.arglist_full}, const char* impl_name) +${kern.pname} ${kern.name}_get_impl(const char* impl_name) { const int index = volk_get_index( get_machine()->${kern.name}_impl_names, get_machine()->${kern.name}_n_impls, impl_name ); - get_machine()->${kern.name}_impls[index]( + return get_machine()->${kern.name}_impls[index]; +} + +void ${kern.name}_manual(${kern.arglist_full}, const char* impl_name) +{ + ${kern.name}_get_impl(impl_name)( ${kern.arglist_names} ); } From e4db17d84092f5638c89a35dc72c98c3846526b3 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Sun, 3 Dec 2023 14:04:10 +0100 Subject: [PATCH 3/6] tests: Add a log info print test Potentially, we want to be more verbose. This is a first effort to improve in this area. Signed-off-by: Johannes Demel --- tests/googletest | 1 + tests/test_volk_32fc_x2_multiply_32fc.cc | 11 ++++++++++- tests/volk_test.cc | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) create mode 160000 tests/googletest diff --git a/tests/googletest b/tests/googletest new file mode 160000 index 000000000..9a32aee22 --- /dev/null +++ b/tests/googletest @@ -0,0 +1 @@ +Subproject commit 9a32aee22d771387c494be2d8519fbdf46a713b2 diff --git a/tests/test_volk_32fc_x2_multiply_32fc.cc b/tests/test_volk_32fc_x2_multiply_32fc.cc index 77daebebb..aa527afce 100644 --- a/tests/test_volk_32fc_x2_multiply_32fc.cc +++ b/tests/test_volk_32fc_x2_multiply_32fc.cc @@ -51,6 +51,7 @@ class volk_32fc_x2_multiply_32fc_test : public VolkTest { volk_32fc_x2_multiply_32fc_manual( result.data(), vec0.data(), vec1.data(), vector_length, impl_name.c_str()); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); } void execute_unaligned(const std::string impl_name) @@ -91,6 +92,9 @@ TEST_P(volk_32fc_x2_multiply_32fc_test, aligned) TEST_P(volk_32fc_x2_multiply_32fc_test, unaligned) { for (auto name : unaligned_impl_names) { + RecordProperty("aligned", false); + RecordProperty("implementation", name); + RecordProperty("size", vector_length); fmt::print( "test unaligned implementation: {:>12}, size={} ...", name, vector_length); auto start = std::chrono::steady_clock::now(); @@ -106,4 +110,9 @@ TEST_P(volk_32fc_x2_multiply_32fc_test, unaligned) INSTANTIATE_TEST_SUITE_P(volk_32fc_x2_multiply_32fc, volk_32fc_x2_multiply_32fc_test, - testing::Values(7, 32, 128, 1023, 131071)); + testing::Values(7, 32, 128, 1023, 131071), + testing::PrintToStringParamName() + // [](const testing::TestParamInfo& info) { + // return fmt::format("{}", info.param); + // } +); diff --git a/tests/volk_test.cc b/tests/volk_test.cc index ac580b40d..6c0589a06 100644 --- a/tests/volk_test.cc +++ b/tests/volk_test.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include From 127228187ffc06179badb84c76e8493f834843de Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Mon, 19 Aug 2024 22:12:28 +0200 Subject: [PATCH 4/6] gtest: Make gtest an install dependency It's probably a good thing to have googletest as an install dependency. Signed-off-by: Johannes Demel --- tests/CMakeLists.txt | 35 ++++++++++------------- tests/googletest | 1 - tests/test_volk_32f_x3_sum_of_poly_32f.cc | 1 - 3 files changed, 15 insertions(+), 22 deletions(-) delete mode 160000 tests/googletest diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 860adb74f..fd9d8b8c4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,9 +6,17 @@ # SPDX-License-Identifier: LGPL-3.0-or-later # -add_subdirectory(googletest) +if(NOT ENABLE_TESTING) + return() +endif(NOT ENABLE_TESTING) -find_package(fmt REQUIRED) +find_package(fmt) +find_package(GTest) + +if(NOT fmt_FOUND OR NOT GTest_FOUND) + message(warning "Missing fmtlib and/or googletest for this test suite") + return() +endif(NOT fmt_FOUND OR NOT GTest_FOUND) file(GLOB volk_test_files "test_*.cc") @@ -18,11 +26,11 @@ add_executable( ${volk_test_files} ) -target_link_libraries( - volk_tests - gtest_main - volk - fmt::fmt +target_link_libraries(volk_tests + PRIVATE + GTest::gtest_main + volk + fmt::fmt ) include(GoogleTest) @@ -37,16 +45,3 @@ target_include_directories(volk_tests PRIVATE ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) - -# if(ENABLE_STATIC_LIBS) -# target_link_libraries(volk_tests PRIVATE volk_static) -# set_target_properties(volk_tests PROPERTIES LINK_FLAGS "-static") -# else() -# target_link_libraries(volk_tests PRIVATE volk) -# endif() - -# install( -# TARGETS volk_tests -# DESTINATION bin -# COMPONENT "volk" -# ) \ No newline at end of file diff --git a/tests/googletest b/tests/googletest deleted file mode 160000 index 9a32aee22..000000000 --- a/tests/googletest +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9a32aee22d771387c494be2d8519fbdf46a713b2 diff --git a/tests/test_volk_32f_x3_sum_of_poly_32f.cc b/tests/test_volk_32f_x3_sum_of_poly_32f.cc index 59c50ebfb..27d972dcf 100644 --- a/tests/test_volk_32f_x3_sum_of_poly_32f.cc +++ b/tests/test_volk_32f_x3_sum_of_poly_32f.cc @@ -137,5 +137,4 @@ TEST_P(volk_32f_x3_sum_of_poly_32f_test, unaligned) INSTANTIATE_TEST_SUITE_P(volk_32f_x3_sum_of_poly_32f, volk_32f_x3_sum_of_poly_32f_test, - // testing::Values(8, 32) testing::Values(7, 32, 128, 1023, 65535, 131071)); From ea1604b15283835a770443350f717412ce8715e9 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Mon, 19 Aug 2024 22:30:42 +0200 Subject: [PATCH 5/6] gtest: Enable GTests in CI workflows We want to gradually migrate to a more stable test framework. This requires that our CI runs the new framework. Here we go! Signed-off-by: Johannes Demel --- .github/workflows/publish_docs.yml | 52 ++++---- .github/workflows/run-tests.yml | 196 ++++++++++++++--------------- 2 files changed, 122 insertions(+), 126 deletions(-) diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index 0990727f5..9bbf5bbdb 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml @@ -7,29 +7,29 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.1.0 - with: - submodules: 'recursive' - - name: Install dependencies - run: sudo apt install python3-mako liborc-dev doxygen - - name: Configure - run: mkdir build && cd build && cmake -DCMAKE_CXX_FLAGS="-Werror" -DBUILD_EXECUTABLE=ON .. - - name: Build - run: cmake --build build --target volk_doc - - name: Setup SSH Keys - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - run: | - ssh-agent -a $SSH_AUTH_SOCK > /dev/null - ssh-add - <<< "${{ secrets.SSH_KEY }}" - mkdir $HOME/.ssh - echo -n "${{ secrets.SSH_KNOWN_HOST }}" > $HOME/.ssh/known_hosts - - name: Upload via SSH - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - TARGET_DIR: "${{ github.ref_type }}/${{ github.ref_name }}" - run: 'tar -cz build/html/ | ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_SERVER }} "mkdir -p /www/${{ env.TARGET_DIR }}/$(date +%Y.%m.%d); cd /www/${{ env.TARGET_DIR }}/$(date +%Y.%m.%d); tar --strip-components=2 -xz; rm /www/${{ env.TARGET_DIR }}/live; cd /www/${{ env.TARGET_DIR }}; ln -sf $(date +%Y.%m.%d) live;"' - - uses: actions/upload-artifact@v4 - with: - name: volk_docs - path: build/html/ + - uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: Install dependencies + run: sudo apt install python3-mako liborc-dev doxygen + - name: Configure + run: mkdir build && cd build && cmake -DCMAKE_CXX_FLAGS="-Werror" -DBUILD_EXECUTABLE=ON .. + - name: Build + run: cmake --build build --target volk_doc + - name: Setup SSH Keys + env: + SSH_AUTH_SOCK: /tmp/ssh_agent.sock + run: | + ssh-agent -a $SSH_AUTH_SOCK > /dev/null + ssh-add - <<< "${{ secrets.SSH_KEY }}" + mkdir $HOME/.ssh + echo -n "${{ secrets.SSH_KNOWN_HOST }}" > $HOME/.ssh/known_hosts + - name: Upload via SSH + env: + SSH_AUTH_SOCK: /tmp/ssh_agent.sock + TARGET_DIR: "${{ github.ref_type }}/${{ github.ref_name }}" + run: 'tar -cz build/html/ | ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_SERVER }} "mkdir -p /www/${{ env.TARGET_DIR }}/$(date +%Y.%m.%d); cd /www/${{ env.TARGET_DIR }}/$(date +%Y.%m.%d); tar --strip-components=2 -xz; rm /www/${{ env.TARGET_DIR }}/live; cd /www/${{ env.TARGET_DIR }}; ln -sf $(date +%Y.%m.%d) live;"' + - uses: actions/upload-artifact@v4 + with: + name: volk_docs + path: build/html/ diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 8fe1daa0b..fb0d0a080 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,49 +18,51 @@ jobs: fail-fast: false matrix: compiler: - - { name: g++-7, cc: gcc-7, cxx: g++-7, distro: ubuntu-20.04 } - - { name: g++-8, cc: gcc-8, cxx: g++-8, distro: ubuntu-20.04 } - - { name: g++-9, cc: gcc-9, cxx: g++-9, distro: ubuntu-latest } - - { name: g++-10, cc: gcc-10, cxx: g++-10, distro: ubuntu-latest } - - { name: clang-7, cc: clang-7, cxx: clang++-7, distro: ubuntu-20.04 } - - { name: clang-8, cc: clang-8, cxx: clang++-8, distro: ubuntu-20.04 } - - { name: clang-9, cc: clang-9, cxx: clang++-9, distro: ubuntu-20.04 } + - { name: g++-9, cc: gcc-9, cxx: g++-9, distro: ubuntu-20.04 } + - { name: g++-10, cc: gcc-10, cxx: g++-10, distro: ubuntu-20.04 } + - { name: g++-11, cc: gcc-11, cxx: g++-11, distro: ubuntu-22.04 } + - { name: g++-12, cc: gcc-12, cxx: g++-12, distro: ubuntu-22.04 } + - { name: g++-13, cc: gcc-13, cxx: g++-13, distro: ubuntu-24.04 } + - { name: g++-14, cc: gcc-14, cxx: g++-14, distro: ubuntu-24.04 } - { name: clang-10, cc: clang-10, cxx: clang++-10, distro: ubuntu-20.04 } - { name: clang-11, cc: clang-11, cxx: clang++-11, distro: ubuntu-20.04 } - - { name: clang-12, cc: clang-12, cxx: clang++-12, distro: ubuntu-latest } - - { name: clang-13, cc: clang-13, cxx: clang++-13, distro: ubuntu-latest } - - { name: clang-14, cc: clang-14, cxx: clang++-14, distro: ubuntu-latest } - # - { name: clang-15, cc: clang-15, cxx: clang++-15, distro: ubuntu-latest } + - { name: clang-12, cc: clang-12, cxx: clang++-12, distro: ubuntu-22.04 } + - { name: clang-13, cc: clang-13, cxx: clang++-13, distro: ubuntu-22.04 } + - { name: clang-14, cc: clang-14, cxx: clang++-14, distro: ubuntu-22.04 } + - { name: clang-15, cc: clang-15, cxx: clang++-15, distro: ubuntu-22.04 } + - { name: clang-16, cc: clang-16, cxx: clang++-16, distro: ubuntu-24.04 } + - { name: clang-17, cc: clang-17, cxx: clang++-17, distro: ubuntu-24.04 } + - { name: clang-18, cc: clang-18, cxx: clang++-18, distro: ubuntu-24.04 } runs-on: ${{ matrix.compiler.distro }} steps: - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: Install dependencies - run: sudo apt install python3-mako liborc-dev ${{ matrix.compiler.name }} - - name: Configure - env: - CC: ${{ matrix.compiler.cc }} - CXX: ${{ matrix.compiler.cxx }} - run: mkdir build && cd build && cmake -DCMAKE_CXX_FLAGS="-Werror" -DBUILD_EXECUTABLE=ON .. - - name: Build - run: | - echo "Build with $(nproc) thread(s)" - cmake --build build -j$(nproc) - - name: Print info - run: | - ./build/cpu_features/list_cpu_features - ./build/apps/volk-config-info --alignment - ./build/apps/volk-config-info --avail-machines - ./build/apps/volk-config-info --all-machines - ./build/apps/volk-config-info --malloc - ./build/apps/volk-config-info --cc - - name: Test - run: | - cd build - ctest -V + - uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: Install dependencies + run: sudo apt install python3-mako liborc-dev libgtest-dev libfmt-dev ${{ matrix.compiler.name }} + - name: Configure + env: + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + run: mkdir build && cd build && cmake -DCMAKE_CXX_FLAGS="-Werror" -DBUILD_EXECUTABLE=ON .. + - name: Build + run: | + echo "Build with $(nproc) thread(s)" + cmake --build build -j$(nproc) + - name: Print info + run: | + ./build/cpu_features/list_cpu_features + ./build/apps/volk-config-info --alignment + ./build/apps/volk-config-info --avail-machines + ./build/apps/volk-config-info --all-machines + ./build/apps/volk-config-info --malloc + ./build/apps/volk-config-info --cc + - name: Test + run: | + cd build + ctest -V build-ubuntu-arm: # The host should always be linux @@ -73,9 +75,6 @@ jobs: fail-fast: false matrix: include: - - arch: aarch64 - distro: ubuntu20.04 - compiler: { name: g++-8, cc: gcc-8, cxx: g++-8 } - arch: aarch64 distro: ubuntu20.04 compiler: { name: g++-9, cc: gcc-9, cxx: g++-9 } @@ -94,6 +93,9 @@ jobs: - arch: aarch64 distro: ubuntu22.04 compiler: { name: clang-14, cc: clang-14, cxx: clang++-14 } + - arch: aarch64 + distro: ubuntu22.04 + compiler: { name: clang-15, cc: clang-15, cxx: clang++-15 } - arch: armv7 distro: ubuntu22.04 compiler: { name: g++, cc: gcc, cxx: g++ } @@ -112,8 +114,8 @@ jobs: steps: - uses: actions/checkout@v4 with: - submodules: 'recursive' - - uses: uraimo/run-on-arch-action@v2.5.0 + submodules: "recursive" + - uses: uraimo/run-on-arch-action@v2.7.2 name: Build in non-x86 container id: build with: @@ -139,7 +141,7 @@ jobs: case "${{ matrix.distro }}" in ubuntu*|jessie|stretch|buster) apt-get update -q -y - apt-get install -q -y git cmake python3-mako liborc-dev ${{ matrix.compiler.name }} + apt-get install -q -y git cmake python3-mako liborc-dev libgtest-dev libfmt-dev ${{ matrix.compiler.name }} ;; fedora*) dnf -y update @@ -169,44 +171,41 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: dependencies - run: sudo apt install python3-mako liborc-dev - - name: configure - run: mkdir build && cd build && cmake -DENABLE_STATIC_LIBS=True -DBUILD_EXECUTABLE=ON .. - - name: build - run: cmake --build build -j$(nproc) - - name: Print info - run: | - ./build/cpu_features/list_cpu_features - ./build/apps/volk-config-info --alignment - ./build/apps/volk-config-info --avail-machines - ./build/apps/volk-config-info --all-machines - ./build/apps/volk-config-info --malloc - ./build/apps/volk-config-info --cc - - name: test - run: cd build && ctest -V - - + - uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: dependencies + run: sudo apt install python3-mako liborc-dev libgtest-dev libfmt-dev + - name: configure + run: mkdir build && cd build && cmake -DENABLE_STATIC_LIBS=True -DBUILD_EXECUTABLE=ON .. + - name: build + run: cmake --build build -j$(nproc) + - name: Print info + run: | + ./build/cpu_features/list_cpu_features + ./build/apps/volk-config-info --alignment + ./build/apps/volk-config-info --avail-machines + ./build/apps/volk-config-info --all-machines + ./build/apps/volk-config-info --malloc + ./build/apps/volk-config-info --cc + - name: test + run: cd build && ctest -V build-windows: - runs-on: windows-latest steps: - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: dependencies - run: pip install mako - - name: configure - run: mkdir build && cd build && cmake .. - - name: build - run: cmake --build build --config Release --target INSTALL -j2 - - name: test - run: cd build && ctest -V -C Release + - uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: dependencies + run: pip install mako + - name: configure + run: mkdir build && cd build && cmake .. + - name: build + run: cmake --build build --config Release --target INSTALL -j4 + - name: test + run: cd build && ctest -V -C Release # build-windows-msys2: # name: Build on windows-latest using MinGW and MSYS2 @@ -226,7 +225,7 @@ jobs: # python-six # mingw-w64-x86_64-gcc # mingw-w64-x86_64-cmake - # - uses: actions/checkout@v2 + # - uses: actions/checkout@v4 # - name: Checkout submodules # run: git submodule update --init --recursive # - name: Configure @@ -242,32 +241,29 @@ jobs: # ctest -V build-macos: - strategy: matrix: - os: [macos-latest, flyci-macos-large-latest-m2] + os: [macos-13, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: dependencies - run: pip3 install --break-system-packages mako && brew install orc - - name: configure - run: mkdir build && cd build && cmake -DBUILD_EXECUTABLE=ON .. - - name: build - run: cmake --build build --config Debug -j3 - - name: Print info - run: | - ./build/cpu_features/list_cpu_features - # ./build/apps/volk-config-info --alignment - # ./build/apps/volk-config-info --avail-machines - # ./build/apps/volk-config-info --all-machines - # ./build/apps/volk-config-info --malloc - # ./build/apps/volk-config-info --cc - - name: test - run: cd build && ctest -V - - + - uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: dependencies + run: pip3 install --break-system-packages mako && brew install orc + - name: configure + run: mkdir build && cd build && cmake -DBUILD_EXECUTABLE=ON .. + - name: build + run: cmake --build build --config Debug -j4 + - name: Print info + run: | + ./build/cpu_features/list_cpu_features + # ./build/apps/volk-config-info --alignment + # ./build/apps/volk-config-info --avail-machines + # ./build/apps/volk-config-info --all-machines + # ./build/apps/volk-config-info --malloc + # ./build/apps/volk-config-info --cc + - name: test + run: cd build && ctest -V From 0858869a5561442cfd24111866f914e4137a0250 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Tue, 20 Aug 2024 23:50:28 +0200 Subject: [PATCH 6/6] tests: Beautify test output We can run an individual test for each implementation now. Further, the test names are easier to recognize. Signed-off-by: Johannes Demel --- tests/CMakeLists.txt | 2 + tests/test_volk_32f_x3_sum_of_poly_32f.cc | 61 +++++++++------------ tests/test_volk_32fc_x2_multiply_32fc.cc | 65 +++++++++-------------- tests/volk_test.cc | 27 ++++++++-- tests/volk_test.h | 36 +++++++++---- 5 files changed, 102 insertions(+), 89 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fd9d8b8c4..42dbeca0f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,6 +26,8 @@ add_executable( ${volk_test_files} ) +target_compile_features(volk_tests PUBLIC cxx_std_20) + target_link_libraries(volk_tests PRIVATE GTest::gtest_main diff --git a/tests/test_volk_32f_x3_sum_of_poly_32f.cc b/tests/test_volk_32f_x3_sum_of_poly_32f.cc index 27d972dcf..746623b9f 100644 --- a/tests/test_volk_32f_x3_sum_of_poly_32f.cc +++ b/tests/test_volk_32f_x3_sum_of_poly_32f.cc @@ -22,8 +22,8 @@ class volk_32f_x3_sum_of_poly_32f_test : public VolkTest protected: void SetUp() override { - initialize_implementation_names(volk_32f_x3_sum_of_poly_32f_get_func_desc()); - initialize_data(GetParam()); + initialize_test(GetParam()); + initialize_data(vector_length); } void initialize_data(const size_t length) @@ -66,6 +66,7 @@ class volk_32f_x3_sum_of_poly_32f_test : public VolkTest result = volk::vector(1, 0.0); ua_result.push_back(result.at(0)); ua_result.push_back(result.at(0)); + tolerance = std::max(expected * 1e-5, 1e-5); } void execute_aligned(const std::string impl_name) @@ -76,6 +77,7 @@ class volk_32f_x3_sum_of_poly_32f_test : public VolkTest cutoff.data(), vector_length, impl_name.c_str()); + EXPECT_NEAR(result.at(0), expected, tolerance); } void execute_unaligned(const std::string impl_name) @@ -86,6 +88,7 @@ class volk_32f_x3_sum_of_poly_32f_test : public VolkTest ua_cutoff.data() + 1, vector_length, impl_name.c_str()); + EXPECT_NEAR(ua_result.at(1), expected, tolerance); } // void TearDown() override {} @@ -99,42 +102,30 @@ class volk_32f_x3_sum_of_poly_32f_test : public VolkTest volk::vector result; volk::vector ua_result; float expected = 0.0f; + float tolerance = 1.0e-5; }; - -TEST_P(volk_32f_x3_sum_of_poly_32f_test, aligned) -{ - for (auto name : implementation_names) { - auto tol = std::max(expected * 1e-5, 1e-5); - fmt::print( - "test aligned implementation: {:>12}, size={} ...", name, vector_length); - auto start = std::chrono::steady_clock::now(); - - execute_aligned(name); - - std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; - fmt::print("\tduration={}\n", elapsed); - EXPECT_NEAR(result.at(0), expected, tol); - } -} - -TEST_P(volk_32f_x3_sum_of_poly_32f_test, unaligned) +TEST_P(volk_32f_x3_sum_of_poly_32f_test, run) { - for (auto name : unaligned_impl_names) { - auto tol = std::max(expected * 1e-5, 1e-5); - fmt::print( - "test unaligned implementation: {:>12}, size={} ...", name, vector_length); - auto start = std::chrono::steady_clock::now(); - - execute_unaligned(name); - - std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; - fmt::print("\tduration={}\n", elapsed); - EXPECT_NEAR(ua_result.at(1), expected, tol); + fmt::print("test {} implementation: {:>12}, size={} ...", + is_aligned_implementation ? "aligned" : "unaligned", + implementation_name, + vector_length); + auto start = std::chrono::steady_clock::now(); + + if (is_aligned_implementation) { + execute_aligned(implementation_name); + } else { + execute_unaligned(implementation_name); } + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); } - -INSTANTIATE_TEST_SUITE_P(volk_32f_x3_sum_of_poly_32f, - volk_32f_x3_sum_of_poly_32f_test, - testing::Values(7, 32, 128, 1023, 65535, 131071)); +INSTANTIATE_TEST_SUITE_P( + volk_32f_x3_sum_of_poly_32f, + volk_32f_x3_sum_of_poly_32f_test, + testing::Combine(testing::ValuesIn(get_kernel_implementation_name_list( + volk_32f_x3_sum_of_poly_32f_get_func_desc())), + testing::ValuesIn(default_vector_sizes)), + generate_volk_test_name()); diff --git a/tests/test_volk_32fc_x2_multiply_32fc.cc b/tests/test_volk_32fc_x2_multiply_32fc.cc index aa527afce..e70031448 100644 --- a/tests/test_volk_32fc_x2_multiply_32fc.cc +++ b/tests/test_volk_32fc_x2_multiply_32fc.cc @@ -11,19 +11,19 @@ #include #include #include +#include #include #include #include #include - class volk_32fc_x2_multiply_32fc_test : public VolkTest { protected: void SetUp() override { - initialize_implementation_names(volk_32fc_x2_multiply_32fc_get_func_desc()); - initialize_data(GetParam()); + initialize_test(GetParam()); + initialize_data(vector_length); } void initialize_data(const size_t length) @@ -61,10 +61,9 @@ class volk_32fc_x2_multiply_32fc_test : public VolkTest vec1.data() + 1, vector_length - 1, impl_name.c_str()); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, ua_result)); } - // void TearDown() override {} - size_t vector_length; volk::vector vec0; volk::vector vec1; volk::vector result; @@ -73,46 +72,30 @@ class volk_32fc_x2_multiply_32fc_test : public VolkTest volk::vector ua_result; }; - -TEST_P(volk_32fc_x2_multiply_32fc_test, aligned) +TEST_P(volk_32fc_x2_multiply_32fc_test, run) { - for (auto name : implementation_names) { - fmt::print( - "test aligned implementation: {:>12}, size={} ...", name, vector_length); - auto start = std::chrono::steady_clock::now(); - - execute_aligned(name); - - std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; - fmt::print("\tduration={}\n", elapsed); - EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); + fmt::print("test {} implementation: {:>12}, size={} ...", + is_aligned_implementation ? "aligned" : "unaligned", + implementation_name, + vector_length); + auto start = std::chrono::steady_clock::now(); + + if (is_aligned_implementation) { + execute_aligned(implementation_name); + } else { + execute_unaligned(implementation_name); } -} - -TEST_P(volk_32fc_x2_multiply_32fc_test, unaligned) -{ - for (auto name : unaligned_impl_names) { - RecordProperty("aligned", false); - RecordProperty("implementation", name); - RecordProperty("size", vector_length); - fmt::print( - "test unaligned implementation: {:>12}, size={} ...", name, vector_length); - auto start = std::chrono::steady_clock::now(); - execute_unaligned(name); - std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; - fmt::print("\tduration={}\n", elapsed); - EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, ua_result)); - } + std::chrono::duration elapsed = std::chrono::steady_clock::now() - start; + fmt::print("\tduration={}\n", elapsed); } -INSTANTIATE_TEST_SUITE_P(volk_32fc_x2_multiply_32fc, - volk_32fc_x2_multiply_32fc_test, - testing::Values(7, 32, 128, 1023, 131071), - testing::PrintToStringParamName() - // [](const testing::TestParamInfo& info) { - // return fmt::format("{}", info.param); - // } -); +INSTANTIATE_TEST_SUITE_P( + volk_32fc_x2_multiply_32fc, + volk_32fc_x2_multiply_32fc_test, + testing::Combine(testing::ValuesIn(get_kernel_implementation_name_list( + volk_32fc_x2_multiply_32fc_get_func_desc())), + testing::ValuesIn(default_vector_sizes)), + generate_volk_test_name()); diff --git a/tests/volk_test.cc b/tests/volk_test.cc index 6c0589a06..bf9a99151 100644 --- a/tests/volk_test.cc +++ b/tests/volk_test.cc @@ -55,7 +55,7 @@ ::testing::AssertionResult AreComplexFloatingPointArraysAlmostEqual(const T& exp return ::testing::AssertionSuccess(); } -std::vector get_kernel_implementation_name_list(volk_func_desc_t desc) +std::vector get_kernel_implementation_name_list(const volk_func_desc_t desc) { std::vector names; for (size_t i = 0; i < desc.n_impls; i++) { @@ -65,13 +65,18 @@ std::vector get_kernel_implementation_name_list(volk_func_desc_t de return names; } +bool is_aligned_implementation_name(const std::string& name) +{ + return name.rfind("a_", 0) == 0; +} + std::tuple, std::vector> -separate_implementations_by_alignment(std::vector names) +separate_implementations_by_alignment(const std::vector& names) { std::vector aligned; std::vector unaligned; for (auto name : names) { - if (name.rfind("a_", 0) == 0) { + if (is_aligned_implementation_name(name)) { aligned.push_back(name); } else { unaligned.push_back(name); @@ -79,3 +84,19 @@ separate_implementations_by_alignment(std::vector names) } return { aligned, unaligned }; } + +std::vector +get_aligned_kernel_implementation_names(const volk_func_desc_t desc) +{ + auto impls = get_kernel_implementation_name_list(desc); + auto [aligned, unaligned] = separate_implementations_by_alignment(impls); + return aligned; +} + +std::vector +get_unaligned_kernel_implementation_names(const volk_func_desc_t desc) +{ + auto impls = get_kernel_implementation_name_list(desc); + auto [aligned, unaligned] = separate_implementations_by_alignment(impls); + return unaligned; +} diff --git a/tests/volk_test.h b/tests/volk_test.h index 20f8780bb..ebc2e3237 100644 --- a/tests/volk_test.h +++ b/tests/volk_test.h @@ -11,27 +11,43 @@ #include #include #include +#include #include +static constexpr std::array default_vector_sizes{ 7, 32, 128, 1023, 131071 }; -std::vector get_kernel_implementation_name_list(volk_func_desc_t desc); +std::vector get_kernel_implementation_name_list(const volk_func_desc_t desc); + +bool is_aligned_implementation_name(const std::string& name); std::tuple, std::vector> -separate_implementations_by_alignment(std::vector names); +separate_implementations_by_alignment(const std::vector& names); + +std::vector +get_aligned_kernel_implementation_names(const volk_func_desc_t desc); +std::vector +get_unaligned_kernel_implementation_names(const volk_func_desc_t desc); + +struct generate_volk_test_name { + template + std::string operator()(const ::testing::TestParamInfo& info) const + { + return fmt::format("{}_{}", std::get<0>(info.param), std::get<1>(info.param)); + } +}; -class VolkTest : public ::testing::TestWithParam +class VolkTest : public ::testing::TestWithParam> { protected: - void initialize_implementation_names(volk_func_desc_t desc) + void initialize_test(const std::tuple& param) { - implementation_names = get_kernel_implementation_name_list(desc); - std::tie(aligned_impl_names, unaligned_impl_names) = - separate_implementations_by_alignment(implementation_names); + std::tie(implementation_name, vector_length) = param; + is_aligned_implementation = is_aligned_implementation_name(implementation_name); } - std::vector implementation_names; - std::vector aligned_impl_names; - std::vector unaligned_impl_names; + std::string implementation_name; + bool is_aligned_implementation; + size_t vector_length; };