subpar
Substitutable parallelization for C++ libraries
|
This repository implements a simple parallelize_range()
function that can be used throughout all of my C++ libaries. By default, it just splits the range of tasks into equi-sized intervals that are executed by different workers. OpenMP is used if it is available, otherwise we spin up a new std::thread
for each interval. Advanced users can define a macro to instruct parallelize_range()
to use their own parallelization mechanism. This allows applications to quickly substitute all instances of parallelize_range()
across all libraries with something more appropriate.
The subpar::parallelize_range()
function requires the number of workers, the number of tasks, and a function that iterates over the range of tasks and executes them in a single worker.
subpar::parallelize_range()
functions will correctly handle exceptions thrown in the user-supplied function. This comes with some slight overhead so the user can set the nothrow_
template parameter to false
if they can guarantee that their supplied functions will not throw.
On occasion, the user has already assigned a task to each worker outside of subpar. This is handled by subpar::parallelize_simple()
, which will execute each task in its own worker without the overhead of task range partitioning.
Check out the reference documentation for more details.
If the SUBPAR_CUSTOM_PARALLELIZE_RANGE
macro is defined, it is used in place of the default behavior whenever subpar::parallelize_range()
is called. The macro should accept exactly the same arguments as subpar::parallelize_range()
, but the macro author is now responsible for distributing tasks among workers. This can be used to inject other parallelization mechanisms like Intel's TBB, TinyThread, Boost, etc. The same approach can be applied to subpar::parallelize_simple()
via the SUBPAR_CUSTOM_PARALLELIZE_SIMPLE
macro.
Users can additionally define the SUBPAR_CUSTOM_PARALLELIZE_RANGE_NOTHROW
or SUBPAR_CUSTOM_PARALLELIZE_SIMPLE_NOTHROW
macros. These will be used in place of their non-NOTHROW
counterparts in the nothrow_ = true
case, providing an optimization opportunity for custom parallelization schemes when exception handling is not required. Note that the non-NOTHROW
macros still need to be defined before the NOTHROW
macros can be used, even if all calls to subpar functions use nothrow_ = true
.
If you're using CMake, you just need to add something like this to your CMakeLists.txt
:
Then you can link to subpar to make the headers available during compilation:
You can install the library by cloning a suitable version of this repository and running the following commands:
Then you can use find_package()
as usual:
If you're not using CMake, the simple approach is to just copy the files in the include/
subdirectory - either directly or with Git submodules - and include their path during compilation with, e.g., GCC's -I
.