Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
orrery::backend::ThreadPool Class Reference

Worker threads and a way to run something on all of them at once. More...

#include <orrery/backend/thread_pool.hpp>

Public Types

enum class  Affinity : std::uint8_t { kUnpinned , kPinned }
 Whether workers are tied to a particular logical processor. More...
using WorkerBody = core::FunctionRef<void(unsigned)>
 What each worker is asked to do, given its own index.

Public Member Functions

 ThreadPool (unsigned worker_count=0, Affinity affinity=Affinity::kUnpinned)
 Start worker_count threads, or one per logical processor if zero.
 ~ThreadPool ()
 Stop the workers and join them.
 ThreadPool (const ThreadPool &)=delete
ThreadPooloperator= (const ThreadPool &)=delete
 ThreadPool (ThreadPool &&)=delete
ThreadPooloperator= (ThreadPool &&)=delete
void dispatch (WorkerBody body)
 Run body(worker) once on every worker and return when all have returned.
unsigned worker_count () const noexcept
Affinity affinity () const noexcept
CoreClass core_class (unsigned worker) const noexcept
 The class of core worker runs on, or kUnknown when unpinned or undiscoverable.

Static Public Member Functions

static unsigned default_worker_count () noexcept
 One worker per logical processor, and never zero.

Detailed Description

Worker threads and a way to run something on all of them at once.

Member Enumeration Documentation

◆ Affinity

enum class orrery::backend::ThreadPool::Affinity : std::uint8_t
strong

Whether workers are tied to a particular logical processor.

Enumerator
kUnpinned 

Let the operating system place the threads.

The default, and on this hardware usually the faster of the two: Windows and Linux both know about hybrid cores and place threads with information a fixed assignment does not have, including what else is running on the machine.

kPinned 

Tie worker w to logical processor w.

A measurement instrument. Attributing idle time to a class of core requires that a worker stay on one core for the whole region, which is not otherwise guaranteed.

Constructor & Destructor Documentation

◆ ThreadPool()

orrery::backend::ThreadPool::ThreadPool ( unsigned worker_count = 0,
Affinity affinity = Affinity::kUnpinned )
explicit

Start worker_count threads, or one per logical processor if zero.

The constructor returns only once every worker has started and, when pinned, settled on its processor. Waiting costs a few hundred microseconds once, and it means the first region measured is not also measuring thread creation.

Member Function Documentation

◆ dispatch()

void orrery::backend::ThreadPool::dispatch ( WorkerBody body)

Run body(worker) once on every worker and return when all have returned.

Call from one thread at a time. The pool is a tool a solver uses to parallelise its own loop, not a general task queue serving many submitters, and one submitter is what every caller in this project is.

body must not throw, for the reason executor.hpp gives.

◆ default_worker_count()

unsigned orrery::backend::ThreadPool::default_worker_count ( )
staticnodiscardnoexcept

One worker per logical processor, and never zero.

hardware_concurrency is permitted to return zero when it cannot tell, and a pool of no threads would never run anything.


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