Lumiera  0.pre.03
»edit your freedom«
work-force.hpp File Reference

Go to the source code of this file.

Description

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.

Warning
concurrency and synchronisation in the Scheduler (which maintains and operates WorkForce) is based on the assumption that all maintenance and organisational work is done chunk-wise by a single worker. Other render activities may proceed in parallel, yet any other worker about to pick the next task has to wait until it is possible to grab the 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.
See also
work-force-test.cpp
scheduler-commutator.hpp usage as part of the Scheduler

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.
 

Function Documentation

◆ performRandomisedSpin()

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.

◆ steppedRandDelay()

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.