Inkscape
Vector Graphics Editor
|
General-purpose, parallel thread dispatch mechanism. More...
#include <dispatch-pool.h>
Public Types | |
using | global_id = int |
using | local_id = int |
using | dispatch_func = std::function< void(global_id, local_id)> |
Public Member Functions | |
dispatch_pool (int size) | |
~dispatch_pool () | |
void | dispatch (int count, dispatch_func function) |
template<typename F > | |
void | dispatch_threshold (int count, bool threshold, F &&function) |
int | size () const |
Private Member Functions | |
void | thread_func (local_id id) |
void | execute_batch (std::unique_lock< std::mutex > &lk, local_id id, int thread_count) |
Private Attributes | |
global_id | _available_work {} |
global_id | _completed_work {} |
global_id | _target_work {} |
bool | _shutdown {} |
std::mutex | _dispatch_lock |
std::mutex | _lock |
std::condition_variable | _available_cv |
std::condition_variable | _completed_cv |
dispatch_func | _function |
std::vector< std::thread > | _threads |
General-purpose, parallel thread dispatch mechanism.
A dispatch is a compute job which is parameterized by a counter. It can also be thought of as a way to parallelize a for loop. For example, the following single-threaded loop
for (int i = 0; i < count; ++i) { do_work(i); }
can be rewritten to use a dispatch_pool and operate in parallel like this:
pool.dispatch(count, [&](int i, int local_id) { do_work(i); });
Finally, it is also possible to perform all jobs on the calling thread unless a threshold condition is met (like dispatch size). This can be used if threading the operation would be less efficient unless the work is at least a certain size:
pool.dispatch_threshold(count, count > 1024, [&](int i, int local_id) { do_work(i); });
Unlike boost's asio::thread_pool, which pushes work for threads onto a queue, this class only supports operation via a counter. The simpler design allows dispatching a very large amount of work (potentially millions of jobs, for every pixel in a megapixel image) with constant memory and space used.
A pool's thread count is fixed upon construction and cannot change during operation. If you allocate work buffers for each thread in the pool, you can use the size() method to determine how many threads it has been created with.
By design, only one dispatch may run at a time. It is safe to call dispatch() from multiple threads without extra locking.
Terminology used is designed to loosely follow that of OpenCL kernels or GL/VK compute shaders:
The first parameter to the callback is global ID. The second parameter, which is unused in the example, is the local ID. The local ID is primarily useful if a work buffer is allocated for each thread in the dispatch_pool ahead of time.
Definition at line 64 of file dispatch-pool.h.
using Inkscape::dispatch_pool::dispatch_func = std::function<void(global_id, local_id)> |
Definition at line 69 of file dispatch-pool.h.
using Inkscape::dispatch_pool::global_id = int |
Definition at line 67 of file dispatch-pool.h.
using Inkscape::dispatch_pool::local_id = int |
Definition at line 68 of file dispatch-pool.h.
|
explicit |
Definition at line 12 of file dispatch-pool.cpp.
References _threads, size(), and thread_func().
Inkscape::dispatch_pool::~dispatch_pool | ( | ) |
Definition at line 24 of file dispatch-pool.cpp.
References _available_cv, _lock, _shutdown, and _threads.
void Inkscape::dispatch_pool::dispatch | ( | int | count, |
dispatch_func | function | ||
) |
Definition at line 40 of file dispatch-pool.cpp.
References _available_work, _completed_cv, _completed_work, _dispatch_lock, _function, _lock, _target_work, execute_batch(), and size().
Referenced by dispatch_threshold(), Inkscape::Filters::filter2D_FIR(), and Inkscape::Filters::filter2D_IIR().
|
inline |
Definition at line 77 of file dispatch-pool.h.
References dispatch().
|
private |
Definition at line 81 of file dispatch-pool.cpp.
References _available_cv, _available_work, _completed_cv, _completed_work, _function, _target_work, end, index, and start.
Referenced by dispatch(), and thread_func().
|
inline |
Definition at line 88 of file dispatch-pool.h.
References _threads.
Referenced by dispatch(), dispatch_pool(), and thread_func().
|
private |
Definition at line 60 of file dispatch-pool.cpp.
References _available_cv, _available_work, _lock, _shutdown, _target_work, execute_batch(), and size().
Referenced by dispatch_pool().
|
private |
Definition at line 106 of file dispatch-pool.h.
Referenced by execute_batch(), thread_func(), and ~dispatch_pool().
|
private |
Definition at line 99 of file dispatch-pool.h.
Referenced by dispatch(), execute_batch(), and thread_func().
|
private |
Definition at line 107 of file dispatch-pool.h.
Referenced by dispatch(), and execute_batch().
|
private |
Definition at line 100 of file dispatch-pool.h.
Referenced by dispatch(), and execute_batch().
|
private |
Definition at line 104 of file dispatch-pool.h.
Referenced by dispatch().
|
private |
Definition at line 108 of file dispatch-pool.h.
Referenced by dispatch(), and execute_batch().
|
private |
Definition at line 105 of file dispatch-pool.h.
Referenced by dispatch(), thread_func(), and ~dispatch_pool().
|
private |
Definition at line 102 of file dispatch-pool.h.
Referenced by thread_func(), and ~dispatch_pool().
|
private |
Definition at line 101 of file dispatch-pool.h.
Referenced by dispatch(), execute_batch(), and thread_func().
|
private |
Definition at line 109 of file dispatch-pool.h.
Referenced by dispatch_pool(), size(), and ~dispatch_pool().