Execution Policy

C++17 has introduced the concept of execution policies that affect how the standard library algorithms are executed. As some parts of the multi_type_vector implementation use the standard library algorithms, you can specify a custom execution policy to be used in those parts in order to potentially improve the run-time performance of those operations.

Currently execution policies are supported only in the SoA variant, and in the following operations:

When using a parallel execution policy, for instance, these operations are performed using multiple threads so that the individual element blocks get processed in parallel. This can potentially improve performance if the multi_type_vector instance contains a sufficiently large number of element blocks, though the actual rate of improvement will depend on how the parallel versions of the standard algorithms are implemented.

The Microsoft C++ compiler natively supports execution policies in its standard library algorithms. When using gcc or clang with libstdc++, you need to have oneTBB installed which incurs additional linking. On Debian-based Linux distributions, you can simply install libtbb-dev and add -ltbb to your linker flag.

Let’s build on the example from the Cloning section and specify the parallel execution policy. All you need to do is to simply add an exec_policy type alias in your traits struct that points to the std::execution::parallel_policy type:

struct mtv_traits : mdds::mtv::default_traits
{
    using exec_policy = std::execution::parallel_policy;

    using block_funcs = mdds::mtv::element_block_funcs<stream_store_block_type>;
};

Then the aforementioned operations will apply this policy.

For the cloning operation, you can additionally specify a custom execution policy for the cloning of the individual values within each element block. All you need to do is to add an exec_policy type alias to the clone_value specialization struct, and have it point to the desired policy type:

namespace mdds { namespace mtv {

template<>
struct clone_value<stream_store*>
{
    using exec_policy = std::execution::parallel_policy;

    stream_store* operator()(const stream_store* src) const
    {
        return new stream_store(src->get_buffer());
    }
};

}}

However, it’s important to benchmark your specific use case since using the parallel execution policy may not always yield better performance due to the added thread management overhead.