NumericAL
A header-only C++20 lexer built on REAL
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
numerical::detail::thread_pool Class Reference

The threads every kernel shares, started once: a parallel_for costs a wake-up, not a thread start. More...

#include <parallel.hpp>

Public Member Functions

 thread_pool (const thread_pool &)=delete
 
thread_pool & operator= (const thread_pool &)=delete
 
 thread_pool (thread_pool &&)=delete
 
thread_pool & operator= (thread_pool &&)=delete
 
 ~thread_pool ()=delete
 
bool try_run (chunk_runner run, const void *body, std::size_t count, std::size_t chunk, std::size_t chunks, std::size_t helpers, side_runner side=nullptr, const void *side_body=nullptr)
 Runs chunks chunks of chunk indices up to count on the caller and at most helpers workers, then rethrows the first exception in index order.
 

Static Public Member Functions

static thread_pool & shared ()
 The pool, started on first use with a worker per hardware thread beside the caller.
 

Private Member Functions

 thread_pool ()=default
 
void start ()
 Starts the workers (after construction: each uses the pool), worker_cores: on Linux one per core, pinned there. Free to move, as a caller is, two threads at times shared one core's hyperthreads (a product of order 1024 on eight AVX2 cores took 8.1 ms, or 10.4 in most processes).
 
void serve (worker_bell &bell)
 A worker on core: waits for a run (polling a while, then asleep), works on it unless it sits it out, waits for the next.
 

Private Attributes

std::mutex lock_
 Guards current_ and generation_.
 
std::vector< std::unique_ptr< worker_bell > > bells_
 Each worker's, set before it starts.
 
std::shared_ptr< pool_job > current_
 The latest run.
 
std::atomic< std::size_t > generation_ {0}
 Counts the runs (polled without the lock).
 
std::atomic< bool > busy_ {false}
 Whether a run holds the pool.
 
std::size_t workers_ {0}
 The threads started.
 
long owner_ {current_process()}
 The process whose threads they are.
 

Detailed Description

The threads every kernel shares, started once: a parallel_for costs a wake-up, not a thread start.

The caller takes chunks beside the workers, each taking the next chunk as it frees up (a slower core takes fewer). One run at a time: a parallel_for while the pool is busy (another thread's, or one nested in a body) runs its chunks itself, with the same result. The pool is never destroyed: its threads wait for work until the process ends, so no static destructor races them.

Definition at line 313 of file parallel.hpp.

Constructor & Destructor Documentation

◆ thread_pool() [1/3]

numerical::detail::thread_pool::thread_pool ( const thread_pool &  )
delete

◆ thread_pool() [2/3]

numerical::detail::thread_pool::thread_pool ( thread_pool &&  )
delete

◆ ~thread_pool()

numerical::detail::thread_pool::~thread_pool ( )
delete

◆ thread_pool() [3/3]

numerical::detail::thread_pool::thread_pool ( )
privatedefault

Member Function Documentation

◆ operator=() [1/2]

thread_pool & numerical::detail::thread_pool::operator= ( const thread_pool &  )
delete

◆ operator=() [2/2]

thread_pool & numerical::detail::thread_pool::operator= ( thread_pool &&  )
delete

◆ serve()

void numerical::detail::thread_pool::serve ( worker_bell &  bell)
inlineprivate

A worker on core: waits for a run (polling a while, then asleep), works on it unless it sits it out, waits for the next.

Definition at line 464 of file parallel.hpp.

◆ shared()

static thread_pool & numerical::detail::thread_pool::shared ( )
inlinestatic

The pool, started on first use with a worker per hardware thread beside the caller.

Exceptions
std::system_errorIf the system starts no thread (the workers already started keep the pool, which a later call starts again).

Definition at line 328 of file parallel.hpp.

◆ start()

void numerical::detail::thread_pool::start ( )
inlineprivate

Starts the workers (after construction: each uses the pool), worker_cores: on Linux one per core, pinned there. Free to move, as a caller is, two threads at times shared one core's hyperthreads (a product of order 1024 on eight AVX2 cores took 8.1 ms, or 10.4 in most processes).

Definition at line 438 of file parallel.hpp.

◆ try_run()

bool numerical::detail::thread_pool::try_run ( chunk_runner  run,
const void *  body,
std::size_t  count,
std::size_t  chunk,
std::size_t  chunks,
std::size_t  helpers,
side_runner  side = nullptr,
const void *  side_body = nullptr 
)
inline

Runs chunks chunks of chunk indices up to count on the caller and at most helpers workers, then rethrows the first exception in index order.

Returns
false, having run nothing, when the pool is busy or belongs to the parent of a forked process. With side, the caller runs it first, while the workers take chunks, and its exception comes back before theirs.

Definition at line 344 of file parallel.hpp.

Member Data Documentation

◆ bells_

std::vector<std::unique_ptr<worker_bell> > numerical::detail::thread_pool::bells_
private

Each worker's, set before it starts.

Definition at line 513 of file parallel.hpp.

◆ busy_

std::atomic<bool> numerical::detail::thread_pool::busy_ {false}
private

Whether a run holds the pool.

Definition at line 516 of file parallel.hpp.

◆ current_

std::shared_ptr<pool_job> numerical::detail::thread_pool::current_
private

The latest run.

Definition at line 514 of file parallel.hpp.

◆ generation_

std::atomic<std::size_t> numerical::detail::thread_pool::generation_ {0}
private

Counts the runs (polled without the lock).

Definition at line 515 of file parallel.hpp.

◆ lock_

std::mutex numerical::detail::thread_pool::lock_
private

Guards current_ and generation_.

Definition at line 512 of file parallel.hpp.

◆ owner_

long numerical::detail::thread_pool::owner_ {current_process()}
private

The process whose threads they are.

Definition at line 521 of file parallel.hpp.

◆ workers_

std::size_t numerical::detail::thread_pool::workers_ {0}
private

The threads started.

Definition at line 517 of file parallel.hpp.


The documentation for this class was generated from the following file: