Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
A pool of workers for multithreaded rendering.
The Lumiera Render Engine is driven by active workers repeatedly pulling the next planned chunk of work; maintaining the internal organisation of the Scheduler is integrated into that pattern as just another activity performed by the workers. As a consequence, there is no need for a central »master« or coordinator to dispatch individual jobs. As long as the worker pool holds active workers, the engine is in running state.
The WorkForce (worker pool service) in turn is passive and fulfils the purpose of holding storage for the active worker objects in a list, pruning terminated entries. Some parameters and configuration is provided to the workers, notably a work functor invoked actively to »pull« work. The return value from this doWork()
-function governs the worker's behaviour, either by prompting to pull further work, by sending a worker into a sleep cycle, perform contention mitigation, or even asking the worker to terminate.
GroomingToken
exclusively. For the WorkForce this usage pattern implies that there is no explicit synchronisation – scaling up and shutting down must be performed non-concurrently. Definition in file work-force.hpp.
#include "vault/common.hpp"
#include "vault/gear/activity.hpp"
#include "lib/meta/function.hpp"
#include "lib/thread.hpp"
#include "lib/nocopy.hpp"
#include "lib/util.hpp"
#include <utility>
#include <chrono>
#include <atomic>
#include <list>
Classes | |
struct | Config |
Base for configuration of the worker pool. More... | |
class | Worker< CONF > |
Individual worker thread: repeatedly pulls the doWork functor. More... | |
class | WorkForce< CONF > |
Pool of worker threads for rendering. More... | |
Typedefs | |
using | Launch = lib::Thread::Launch |
using | SIG_FinalHook = void(bool) |
config should define callable invoked at exit (argument: isFailure) | |
using | SIG_WorkFun = activity::Proc(void) |
config should define a callable with this signature to perform work | |
Functions | |
void | performRandomisedSpin (size_t, size_t) |
This is part of the weak level of anti-contention measures. More... | |
microseconds | steppedRandDelay (size_t, size_t) |
Calculate the delay time for a stronger anti-contention wait. More... | |
size_t | thisThreadHash () |
Variables | |
const size_t | CONTEND_RANDOM_STEP = 11 |
stepping for randomisation of anti-contention measures | |
const size_t | CONTEND_SATURATION = CONTEND_STARK_LIMIT + 4 |
upper limit for the contention event count | |
const size_t | CONTEND_SOFT_FACTOR = 100 |
base counter for a spinning wait loop | |
const size_t | CONTEND_SOFT_LIMIT = 3 |
zone for soft anti-contention measures, counting continued contention events | |
const size_t | CONTEND_STARK_LIMIT = CONTEND_SOFT_LIMIT + 5 |
zone for stark measures, performing a sleep with exponential stepping | |
const microseconds | CONTEND_WAIT = 100us |
base time unit for the exponentially stepped-up sleep delay in case of contention | |
const double | MAX_OVERPROVISIONING = 3.0 |
safety guard to prevent catastrophic over-provisioning | |
Namespaces | |
vault | |
Vault-Layer implementation namespace root. | |
vault::gear | |
Active working gear and plumbing. | |
void performRandomisedSpin | ( | size_t | stepping, |
size_t | randFact | ||
) |
This is part of the weak level of anti-contention measures.
When a worker is kicked out from processing due to contention, the immediate reaction is to try again; if this happens repeatedly however, increasingly strong delays are interspersed. Within the weak zone, a short spinning wait is performed, and then the thread requests a yield()
from the OS scheduler; this cycle is repeated.
Definition at line 75 of file work-force.cpp.
References vault::gear::anonymous_namespace{work-force.hpp}::CONTEND_SOFT_FACTOR.
microseconds steppedRandDelay | ( | size_t | stepping, |
size_t | randFact | ||
) |
Calculate the delay time for a stronger anti-contention wait.
If the contention lasts, the worker must back out temporarily to allow other workers to catch up. The delay time is stepped up quickly up to a saturation level, where the worker sleeps in the microseconds range — this level is chosen as a balance between retaining some reactivity vs not incurring additional load. The stepping of the anti-contention measures is »sticky« to some degree, because it is not set to zero, once contention ends, but rather stepped down gradually.
Definition at line 91 of file work-force.cpp.
References vault::gear::anonymous_namespace{work-force.hpp}::CONTEND_WAIT.