diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index 0990727f..9bbf5bbd 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 8fe1daa0..fb0d0a08 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 01f0acb3..f91f88af 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 00000000..42dbeca0 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# Copyright 2022, 2024 Johannes Demel +# +# This file is part of VOLK. +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +if(NOT ENABLE_TESTING) + return() +endif(NOT ENABLE_TESTING) + +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") + +add_executable( + volk_tests + volk_test.cc + ${volk_test_files} +) + +target_compile_features(volk_tests PUBLIC cxx_std_20) + +target_link_libraries(volk_tests + PRIVATE + GTest::gtest_main + volk + fmt::fmt +) + +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} +) 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 00000000..746623b9 --- /dev/null +++ b/tests/test_volk_32f_x3_sum_of_poly_32f.cc @@ -0,0 +1,131 @@ +/* -*- 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_test(GetParam()); + initialize_data(vector_length); + } + + 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)); + tolerance = std::max(expected * 1e-5, 1e-5); + } + + 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()); + EXPECT_NEAR(result.at(0), expected, tolerance); + } + + 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()); + EXPECT_NEAR(ua_result.at(1), expected, tolerance); + } + + // 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; + float tolerance = 1.0e-5; +}; + +TEST_P(volk_32f_x3_sum_of_poly_32f_test, run) +{ + 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::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 new file mode 100644 index 00000000..e7003144 --- /dev/null +++ b/tests/test_volk_32fc_x2_multiply_32fc.cc @@ -0,0 +1,101 @@ +/* -*- 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 +#include + +class volk_32fc_x2_multiply_32fc_test : public VolkTest +{ +protected: + void SetUp() override + { + initialize_test(GetParam()); + initialize_data(vector_length); + } + + 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); + } + + 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()); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, result)); + } + + 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()); + EXPECT_TRUE(AreComplexFloatingPointArraysAlmostEqual(expected, ua_result)); + } + + volk::vector vec0; + volk::vector vec1; + volk::vector result; + volk::vector expected; + + volk::vector ua_result; +}; + +TEST_P(volk_32fc_x2_multiply_32fc_test, run) +{ + 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_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 new file mode 100644 index 00000000..bf9a9915 --- /dev/null +++ b/tests/volk_test.cc @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include +#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(const 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; +} + +bool is_aligned_implementation_name(const std::string& name) +{ + return name.rfind("a_", 0) == 0; +} + +std::tuple, std::vector> +separate_implementations_by_alignment(const std::vector& names) +{ + std::vector aligned; + std::vector unaligned; + for (auto name : names) { + if (is_aligned_implementation_name(name)) { + aligned.push_back(name); + } else { + unaligned.push_back(name); + } + } + 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 new file mode 100644 index 00000000..ebc2e323 --- /dev/null +++ b/tests/volk_test.h @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 Johannes Demel + * + * This file is part of VOLK + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include +#include +#include +#include +#include +#include + +static constexpr std::array default_vector_sizes{ 7, 32, 128, 1023, 131071 }; + +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(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> +{ +protected: + void initialize_test(const std::tuple& param) + { + std::tie(implementation_name, vector_length) = param; + is_aligned_implementation = is_aligned_implementation_name(implementation_name); + } + + std::string implementation_name; + bool is_aligned_implementation; + size_t vector_length; +}; + + +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 62a9400a..63c52b92 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} ); }