Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add workflows
Browse files Browse the repository at this point in the history
alugowski committed Nov 13, 2023
1 parent cb92938 commit a59a899
Showing 9 changed files with 165 additions and 25 deletions.
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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"
87 changes: 87 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -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/*
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions benchmark/utils.hpp
Original file line number Diff line number Diff line change
@@ -8,7 +8,9 @@
#define POOLSTL_BENCH_UTILS_HPP

#include <algorithm>
#ifdef POOLSTL_BENCH_STD_PAR
#include <execution>
#endif
#include <numeric>
#include <utility>
#include <vector>
@@ -40,11 +42,13 @@ template <> struct policy<poolstl::execution::par_pool> {
return poolstl::execution::par_pool(pool);
};
};
#ifdef POOLSTL_BENCH_STD_PAR
template <> struct policy<std_par> {
constexpr static const std::execution::parallel_policy& get() {
return std::execution::par;
};
};
#endif

template <typename T=int>
std::vector<T> iota_vector(size_t size, T init=0) {
24 changes: 19 additions & 5 deletions include/poolstl/algorithm
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
#include "internal/utils.hpp"
#include "execution"

// TODO TEMP ///////////////////////////////////////////////////////////////////
#include <iostream>

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<void>> 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;
}
}

20 changes: 9 additions & 11 deletions include/poolstl/execution
Original file line number Diff line number Diff line change
@@ -41,26 +41,24 @@ namespace poolstl {
}

template <typename ExecutionPolicy>
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>(par_pool& policy) {
return policy.pool;
}

template <typename T> 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 <class T>
inline constexpr bool is_poolstl_execution_policy_v = is_poolstl_execution_policy<T>::value;

template <class ExecutionPolicy, class Tp>
using enable_if_poolstl_execution_policy =
typename std::enable_if<
is_poolstl_execution_policy_v<
typename std::remove_cv<typename std::remove_reference<ExecutionPolicy>::type>::type>,
is_poolstl_execution_policy<
typename std::remove_cv<typename std::remove_reference<ExecutionPolicy>::type>::type>::value,
Tp>::type;
}
}
15 changes: 8 additions & 7 deletions include/poolstl/internal/utils.hpp
Original file line number Diff line number Diff line change
@@ -13,15 +13,16 @@

#include <cstddef>

namespace poolstl::internal {
namespace poolstl {
namespace internal {

template<typename Iterator>
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<typename Iterator>
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
10 changes: 9 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
17 changes: 17 additions & 0 deletions tests/cpp11_test.cpp
Original file line number Diff line number Diff line change
@@ -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 <iostream>

#include <poolstl/poolstl.hpp>

int main() {
std::vector<int> 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;
}

0 comments on commit a59a899

Please sign in to comment.