From a59a89909be8c94b03b9ed7105e8817cf4ead3fc Mon Sep 17 00:00:00 2001 From: Adam Lugowski Date: Sun, 12 Nov 2023 17:55:11 -0800 Subject: [PATCH] Add workflows --- .github/dependabot.yml | 8 +++ .github/workflows/tests.yml | 87 ++++++++++++++++++++++++++++++ README.md | 5 +- benchmark/utils.hpp | 4 ++ include/poolstl/algorithm | 24 +++++++-- include/poolstl/execution | 20 ++++--- include/poolstl/internal/utils.hpp | 15 +++--- tests/CMakeLists.txt | 10 +++- tests/cpp11_test.cpp | 17 ++++++ 9 files changed, 165 insertions(+), 25 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/tests.yml create mode 100644 tests/cpp11_test.cpp diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b116b86 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + # See https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot + interval: "weekly" \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..cdaf6a6 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,87 @@ +name: tests + +on: + push: + pull_request: + +jobs: + build: + name: ${{matrix.os}} ${{ matrix.description }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + # oldest LLVM that the install-llvm-action action is able to install + description: "LLVM 5" + llvm-version: "5" + + - os: ubuntu-20.04 + # oldest GCC that the setup-gcc action is able to install + description: "GCC 7" + gcc-version: "7" + cmake-version: "3.18" + + - os: ubuntu-latest + description: "GCC 13" + gcc-version: "13" + + - os: macos-latest + # uses Apple Clang + + - os: windows-latest + # uses MSVC + + steps: + - uses: actions/checkout@v4 + + - name: Install TBB (Ubuntu) + if: contains(matrix.os, 'ubuntu') + run: sudo apt-get install -y libtbb-dev + + - name: Install TBB (macOS) + if: contains(matrix.os, 'macos') + run: brew install tbb + + - name: Setup GCC + uses: egor-tensin/setup-gcc@v1 + if: ${{ matrix.gcc-version != '' }} + with: + version: ${{ matrix.gcc-version }} + + - name: Setup LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + if: ${{ matrix.llvm-version != '' }} + with: + version: ${{ matrix.llvm-version }} + env: true + + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v1 + if: ${{ matrix.cmake-version != '' }} + with: + cmake-version: ${{ matrix.cmake-version }} + + - name: Build and Test + run: | + cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Debug -DPOOLSTL_TEST=ON -DPOOLSTL_TEST_COVERAGE=ON + cmake --build build/ --config Debug + cd build/tests + ctest -C Debug --output-on-failure --verbose + shell: bash + + - name: Benchmark + if: ${{ matrix.gcc-version != '7' }} + run: | + cmake -S . -B bench_build/ -DCMAKE_BUILD_TYPE=Release -DPOOLSTL_BENCH=ON + cmake --build bench_build/ --config Release + ./bench_build/benchmark/poolstl_bench + shell: bash + + - name: Upload Coverage to Codecov + if: contains(matrix.os, 'ubuntu') + uses: codecov/codecov-action@v3 + with: + gcov: true + gcov_include: include/* diff --git a/README.md b/README.md index ef5525c..9372ce5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ +[![tests](https://github.com/alugowski/poolSTL/actions/workflows/tests.yml/badge.svg)](https://github.com/alugowski/poolSTL/actions/workflows/tests.yml) +[![codecov](https://codecov.io/gh/alugowski/poolSTL/branch/main/graph/badge.svg?token=M9J4azRYyI)](https://codecov.io/gh/alugowski/poolSTL) + # poolSTL -Thread pool-based implementation of [parallel standard library algorithms](https://en.cppreference.com/w/cpp/algorithm#Execution_policies). +Thread pool-based implementation of [parallel standard library algorithms](https://en.cppreference.com/w/cpp/algorithm). Those algorithms are great, but compiler support is inconsistent. PoolSTL is a *supplement* to fill in the support gaps so we can use parallel algorithms now. diff --git a/benchmark/utils.hpp b/benchmark/utils.hpp index db4ce81..3ad5738 100644 --- a/benchmark/utils.hpp +++ b/benchmark/utils.hpp @@ -8,7 +8,9 @@ #define POOLSTL_BENCH_UTILS_HPP #include +#ifdef POOLSTL_BENCH_STD_PAR #include +#endif #include #include #include @@ -40,11 +42,13 @@ template <> struct policy { return poolstl::execution::par_pool(pool); }; }; +#ifdef POOLSTL_BENCH_STD_PAR template <> struct policy { constexpr static const std::execution::parallel_policy& get() { return std::execution::par; }; }; +#endif template std::vector iota_vector(size_t size, T init=0) { diff --git a/include/poolstl/algorithm b/include/poolstl/algorithm index 76dc87c..9f98fb6 100644 --- a/include/poolstl/algorithm +++ b/include/poolstl/algorithm @@ -12,6 +12,9 @@ #include "internal/utils.hpp" #include "execution" +// TODO TEMP /////////////////////////////////////////////////////////////////// +#include + namespace std { /** * See std::for_each https://en.cppreference.com/w/cpp/algorithm/for_each @@ -21,23 +24,34 @@ namespace std { for_each(ExecutionPolicy &&policy, InputIt first, InputIt last, UnaryFunction f) { using namespace ::poolstl::internal; ::std::vector<::std::future> futures; - auto chunk_size = get_chunk_size(first, last, pool(policy).get_num_threads()); + auto chunk_size = get_chunk_size(first, last, 2);//pool(policy).get_num_threads()); - while (first < last) { + std::cout << "-----------------\nstart. " << "n=" << (last-first) << " p=" << pool(policy).get_num_threads() << " chunk_size=" << chunk_size << std::endl; +// std::cout << "{"; +// std::for_each(first, std::min(first+200, last), [](int x) {std::cout << x << " ";}); +// std::cout << "}" << std::endl; + while (first != last) { InputIt loop_end = ::std::min(first + chunk_size, last); - futures.emplace_back(pool(policy).submit([&](InputIt chunk_start, InputIt chunk_stop) { - for (; chunk_start != chunk_stop; ++chunk_start) { - f(*chunk_start); + std::cout << " submitting" << std::endl; + futures.emplace_back(pool(policy).submit([&f](InputIt chunk_first, InputIt chunk_last) { +// std::cout << " worker start\n"; + for (; chunk_first != chunk_last; ++chunk_first) { +// std::cout << " body for " << std::this_thread::get_id() << " " << *chunk_start << " " << std::endl; +// std::cout << " body for " << *chunk_start << " " << std::endl; + f(*chunk_first); } +// std::cout << " worker end\n"; }, first, loop_end)); first = loop_end; } + std::cout << " begin futures" << std::endl; for (auto &future: futures) { future.get(); } + std::cout << "done" << std::endl; } } diff --git a/include/poolstl/execution b/include/poolstl/execution index dd18158..81777e5 100644 --- a/include/poolstl/execution +++ b/include/poolstl/execution @@ -41,26 +41,24 @@ namespace poolstl { } template - ttp::task_thread_pool& pool(ExecutionPolicy& policy) { - if constexpr (ExecutionPolicy::use_default_pool()) { - return *get_default_pool(); - } else { - return policy.pool; - } + ttp::task_thread_pool& pool(ExecutionPolicy&) { + return *get_default_pool(); + } + + template <> + inline ttp::task_thread_pool& pool(par_pool& policy) { + return policy.pool; } template struct is_poolstl_execution_policy : std::false_type {}; template <> struct is_poolstl_execution_policy<::poolstl::execution::parallel_policy> : std::true_type {}; template <> struct is_poolstl_execution_policy<::poolstl::execution::par_pool> : std::true_type {}; - template - inline constexpr bool is_poolstl_execution_policy_v = is_poolstl_execution_policy::value; - template using enable_if_poolstl_execution_policy = typename std::enable_if< - is_poolstl_execution_policy_v< - typename std::remove_cv::type>::type>, + is_poolstl_execution_policy< + typename std::remove_cv::type>::type>::value, Tp>::type; } } diff --git a/include/poolstl/internal/utils.hpp b/include/poolstl/internal/utils.hpp index 296dbd2..be55638 100644 --- a/include/poolstl/internal/utils.hpp +++ b/include/poolstl/internal/utils.hpp @@ -13,15 +13,16 @@ #include -namespace poolstl::internal { +namespace poolstl { + namespace internal { - template - std::size_t get_chunk_size(Iterator first, Iterator last, unsigned int num_threads) { - std::size_t num_steps = (last - first); - auto remainder = num_steps % num_threads; - return (num_steps / num_threads) + (remainder > 0 ? 1 : 0); + template + std::size_t get_chunk_size(Iterator first, Iterator last, unsigned int num_threads) { + std::size_t num_steps = (last - first); + auto remainder = num_steps % num_threads; + return (num_steps / num_threads) + (remainder > 0 ? 1 : 0); + } } - } #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1462f1b..38c6cb8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,7 +22,7 @@ Include(FetchContent) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.3.2 + GIT_TAG v3.4.0 GIT_SHALLOW TRUE EXCLUDE_FROM_ALL ) @@ -35,4 +35,12 @@ include(Catch) add_executable(poolstl_test poolstl_test.cpp) target_link_libraries(poolstl_test PRIVATE Catch2::Catch2WithMain poolSTL::poolSTL) +target_compile_definitions(poolstl_test PRIVATE CATCH_CONFIG_FAST_COMPILE) +# Catch2 requires C++14 +target_compile_features(poolstl_test PUBLIC cxx_std_14) + catch_discover_tests(poolstl_test) + +add_executable(cpp11_test cpp11_test.cpp) +target_link_libraries(cpp11_test PUBLIC poolSTL::poolSTL) +target_compile_features(cpp11_test PUBLIC cxx_std_11) diff --git a/tests/cpp11_test.cpp b/tests/cpp11_test.cpp new file mode 100644 index 0000000..e266ed6 --- /dev/null +++ b/tests/cpp11_test.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2023 Adam Lugowski. All rights reserved. +// Use of this source code is governed by: +// the BSD 2-clause license, the MIT license, or at your choosing the BSL-1.0 license found in the LICENSE.*.txt files. +// SPDX-License-Identifier: BSD-2-Clause OR MIT OR BSL-1.0 + +#include + +#include + +int main() { + std::vector v = {0, 1, 2, 3, 4, 5}; + std::for_each(poolstl::par, v.cbegin(), v.cend(), [](int x) { + std::cout << x << " "; + }); + std::cout << std::endl; + return 0; +}