A modern thread pool implementation based on C++20

thread-pool

say thanks Discord

Ubuntu Windows Style Install

A simple, functional thread pool implementation using pure C++20.

Features

  • Built entirely with C++20
  • Enqueue tasks with or without tracking results

Integration

dp::thread-pool is a header only library. All the files needed are in include/thread_pool.

CMake

ThreadPool defines two CMake targets:

  • ThreadPool::ThreadPool
  • dp::thread-pool

You can then use find_package():

find_package(dp::thread-pool REQUIRED)

Alternatively, you can use something like CPM which is based on CMake's Fetch_Content module.

CPMAddPackage(
    NAME thread-pool
    GITHUB_REPOSITORY DeveloperPaul123/thread-pool
    GIT_TAG #0cea9c12fb30cb677696c0dce6228594ce26171a change this to latest commit or release tag
)

Usage

Simple example:

// create a thread pool with a specified number of threads.
dp::thread_pool pool(4);

// add tasks, in this case without caring about results of individual tasks
pool.enqueue_detach([](int value) { /*...your task...*/ }, 34);
pool.enqueue_detach([](int value) { /*...your task...*/ }, 37);
pool.enqueue_detach([](int value) { /*...your task...*/ }, 38);
// and so on..

You can see other examples in the /examples folder.

Benchmarks

See the ./benchmark folder for the benchmark code. The benchmarks are set up to compare matrix multiplication using the dp::thread_pool versus std::async. A summary of the comparisons is below. Benchmarks were run using the windows-release CMake preset (see CMakePresets.json).

Machine Specs

  • AMD Ryzen 7 1800X (16 X 3593 MHz CPUs)
  • CPU Caches:
    • L1 Data 32 KiB (x8)
    • L1 Instruction 64 KiB (x8)
    • L2 Unified 512 KiB (x8)
    • L3 Unified 8192 KiB (x2)
  • 32 GB RAM

Summary of Results

Matrix sizes are all square (MxM). Each multiplication is (MxM) * (MxM) where * refers to a matrix multiplication operation.

Matrix Size Number of multiplications std::async time (ms) dp::thread_pool time (ms)
8 25,000 77.9 198
64 5,000 100 84.9
256 250 295 59.0
512 75 713 69.3
1024 10 1160 73.8

Building

This project has been built with:

  • Visual Studio 2022
  • Clang 10.+ (via WSL on Windows)
  • GCC 11.+ (vis WSL on Windows)
  • CMake 3.21+

To build, run:

cmake -S . -B build
cmake --build build

Build Options

Option Description Default
TP_BUILD_TESTS Turn on to build unit tests. Required for formatting build targets. ON
TP_BUILD_EXAMPLES Turn on to build examples ON

Run clang-format

Use the following commands from the project's root directory to check and fix C++ and CMake source style. This requires clang-format, cmake-format and pyyaml to be installed on the current system. To use this feature you must turn on TP_BUILD_TESTS.

# view changes
cmake --build build/test --target format

# apply changes
cmake --build build/test --target fix-format

See Format.cmake for details.

Build the documentation

The documentation is automatically built and published whenever a GitHub Release is created. To manually build documentation, call the following command.

cmake -S documentation -B build/doc
cmake --build build/doc --target GenerateDocs
# view the docs
open build/doc/doxygen/html/index.html

To build the documentation locally, you will need Doxygen and Graphviz on your system.

Contributing

Contributions are very welcome. Please see contribution guidelines for more info.

License

The project is licensed under the MIT license. See LICENSE for more details.

Author


@DeveloperPaul123
Comments
  • use feature test macro to check feature available

    use feature test macro to check feature available

    Reason

    thread-pool is a great modern and tiny thread pool. However, using the compiler version to check move_only_function is not solid. For example:

    I used g++-12 (Ubuntu 12.1.0-2ubuntu1~22.04) 12.1.0. The library could not compile due to:

    error: ‘move_only_function’ in namespace ‘std’ does not name a template type 25 | using default_function_type = std::move_only_function<void()>; | ^~~~~~~~~~~~~~~~~~

    Here is the ci for detailed information.

    Hence, I tried to use feature testing instead and it works well.

    I am sure that I may have missed something. :)

  • How could we declare a variable or pointer of  dp::thread_pool

    How could we declare a variable or pointer of dp::thread_pool

    How could we declare variable dp::thread_pool, for example, //in a header h dp::thread_pool pool_var; //Or dp::thread_pool * pool_ptr; in a cpp pool_var = dp::thread_pool();

       dp::thread_pool pool
       pool_ptr = &pool;
    
  • Build tests with fsanitize address on

    Build tests with fsanitize address on

    Changes

    • Tests are now build with address sanitizer support on all supported platforms
    • New test case for passing a variable reference as a function parameter to the thread pool using std::ref()
    • Simplify CMake set up and automatically detect maximum C++ standard available to the compiler.

    Fixes #17

  • [BUG] Version Header is Installed in Wrong Directory

    [BUG] Version Header is Installed in Wrong Directory

    Currently, the automatically generated version.h header is installed in the wrong directory. It is currently under the include path of threadpool but this does not match the thread_pool include directory name that is currently used by the project.

  • [FEATURE] Build Unit Tests with ASAN Enabled

    [FEATURE] Build Unit Tests with ASAN Enabled

    When building the unit tests, we should build with address sanitizer enabled. https://devblogs.microsoft.com/cppblog/addresssanitizer-asan-for-windows-with-msvc/

  • Distribute Task Workload Across Threads Based on Thread Performance

    Distribute Task Workload Across Threads Based on Thread Performance

    Summary

    Switched to using a single task queue for all threads and a std::condition_variable_any to wake the threads when there is work available. This serves to better balance work loads and ensures the total work completes as quickly as possible.

    Fixed

    • #4
    • Minor issues in documentation

    Changed

    • Removed front() and back() member functions from dp::thread_safe_queue.
    • Use a single task queue for all threads
  • [FEATURE] Improve Task Load Distribution Among Threads

    [FEATURE] Improve Task Load Distribution Among Threads

    In the case that tasks don't all take the same amount of time, this could skew the work loads to be "harder" on certain threads, instead of spreading the work uniformly across threads.

    One possible solution for this is to use a single work queue for all threads instead of having one per thread. See this for more info.

  • Improvements and Simplifications to ThreadPool

    Improvements and Simplifications to ThreadPool

    Improvements/changes largely based on feedback from Code Review and Reddit

    Changed

    • Simplified class definition and removed unused typedefs (YAGNI)
    • Also removed Queue template parameter (also YAGNI)
    • Use std::deque instead of std::queue in dp::thread_safe_queue
    • Use std::deque in dp::thread_pool so that usage of std::unique_ptr is no longer needed for internal task objects.

    Fixed

    • Issues with dp::thread_safe_queue's usage of lock guards before notifying threads of new data being available.
    • Ensure that all tasks complete before the thread pool is destroyed.
  • Fix Unit Tests

    Fix Unit Tests

    Fixed

    • Issues with running unit tests with ctest.

    Added

    • Basic unit test for queue type.

    Changed

    • Changed queue class name from safe_queue to thread_safe_queue.
  • [FEATURE] Add bulk enqueue functions

    [FEATURE] Add bulk enqueue functions

    Description

    Would be good to add versions of enqueue() and enqueue_detach() that would allow for submission of multiple tasks at once so that they can be batched.

  • [FEATURE] Investigate Using a Lock Free Queue

    [FEATURE] Investigate Using a Lock Free Queue

    I'm curious to see if a lock-free queue significantly improves performance for the thread pool. We should do some tests with industry standard lock free queues in combination with std::move_only_function to see the difference in performance.

    Queues/deques to test:

    • https://github.com/ConorWilliams/ConcurrentDeque
    • https://github.com/cameron314/concurrentqueue
  • Adding support for using this thread pool with coroutines

    Adding support for using this thread pool with coroutines

    Note This is on hold until I can ensure that the necessary build flags are properly set in the dp::thread-pool for coroutine support. It seems that down-stream projects for coroutines don't set these in the targets properly but I want dp::thread-pool to do this.

    Changes

    • Updated CPM.cmake version
    • Added schedule() function to allow for running coroutines on the thread pool
    • Added batch enqueue() function to better compare to coroutine performance
Thread-pool-cpp - High performance C++11 thread pool

thread-pool-cpp It is highly scalable and fast. It is header only. No external dependencies, only standard library needed. It implements both work-ste

Dec 17, 2022
A modern thread pool implementation based on C++20
A modern thread pool implementation based on C++20

thread-pool A simple, functional thread pool implementation using pure C++20. Features Built entirely with C++20 Enqueue tasks with or without trackin

Dec 22, 2022
CTPL - Modern and efficient C++ Thread Pool Library

CTPL Modern and efficient C++ Thread Pool Library A thread pool is a programming pattern for parallel execution of jobs, http://en.wikipedia.org/wiki/

Dec 22, 2022
An ultra-simple thread pool implementation for running void() functions in multiple worker threads
An ultra-simple thread pool implementation for running void() functions in multiple worker threads

void_thread_pool.cpp © 2021 Dr Sebastien Sikora. [email protected] Updated 06/11/2021. What is it? void_thread_pool.cpp is an ultra-simple

Nov 19, 2021
ThreadPool - A simple C++11 Thread Pool implementation

ThreadPool A simple C++11 Thread Pool implementation. Basic usage: // create thread pool with 4 worker threads ThreadPool pool(4); // enqueue and sto

Jan 7, 2023
Pool is C++17 memory pool template with different implementations(algorithms)

Object Pool Description Pool is C++17 object(memory) pool template with different implementations(algorithms) The classic object pool pattern is a sof

Nov 18, 2022
High Performance Linux C++ Network Programming Framework based on IO Multiplexing and Thread Pool

Kingpin is a C++ network programming framework based on TCP/IP + epoll + pthread, aims to implement a library for the high concurrent servers and clie

Oct 19, 2022
A easy to use multithreading thread pool library for C. It is a handy stream like job scheduler with an automatic garbage collector. This is a multithreaded job scheduler for non I/O bound computation.

A easy to use multithreading thread pool library for C. It is a handy stream-like job scheduler with an automatic garbage collector for non I/O bound computation.

Jun 4, 2022
A C++17 thread pool for high-performance scientific computing.

We present a modern C++17-compatible thread pool implementation, built from scratch with high-performance scientific computing in mind. The thread pool is implemented as a single lightweight and self-contained class, and does not have any dependencies other than the C++17 standard library, thus allowing a great degree of portability

Jan 4, 2023
An easy to use C++ Thread Pool

mvThreadPool (This library is available under a free and permissive license) mvThreadPool is a simple to use header only C++ threadpool based on work

Dec 8, 2022
EOSP ThreadPool is a header-only templated thread pool writtent in c++17.

EOSP Threadpool Description EOSP ThreadPool is a header-only templated thread pool writtent in c++17. It is designed to be easy to use while being abl

Apr 22, 2022
Work Stealing Thread Pool

wstpool Work Stealing Thread Pool, Header Only, C++ Threads Consistent with the C++ async/future programming model. Drop-in replacement for 'async' fo

Oct 29, 2022
MAN - Man is Thread Pool in C++17

Introduction MAN is a ThreadPool wrote in C++17. The name is chosen because, at least in France, it is said that men are not able to do several things

Mar 6, 2022
ThreadPool - A fastest, exception-safety and pure C++17 thread pool.

Warnings Since commit 468129863ec65c0b4ede02e8581bea682351a6d2, I move ThreadPool to C++17. (To use std::apply.) In addition, the rule of passing para

Dec 28, 2022
Objectpool - Object pool implementation in C++11

Object pool allocator This is a C++11 implementation of an object pool allocator. For more information on object pool allocators and their purpose see

Nov 3, 2022
BabyCoin: mining pool

BabyCoin Pool Based on cryptonote-nodejs-pool cryptonote-nodejs-pool High performance Node.js (with native C addons) mining pool for CryptoNote based

May 15, 2022
A hybrid thread / fiber task scheduler written in C++ 11

Marl Marl is a hybrid thread / fiber task scheduler written in C++ 11. About Marl is a C++ 11 library that provides a fluent interface for running tas

Jan 4, 2023
Simple and fast C library implementing a thread-safe API to manage hash-tables, linked lists, lock-free ring buffers and queues

libhl C library implementing a set of APIs to efficiently manage some basic data structures such as : hashtables, linked lists, queues, trees, ringbuf

Dec 3, 2022
Fork of rpmalloc to be used with single thread applications and old C compilers

srpmalloc - Small rpmalloc This is a fork of rpmalloc, with the intent to be used in single threaded applications only, with old C99 compilers, and in

Oct 28, 2022