C++算法是一组预定义函数,可以对容器(例如数组、向量和列表)执行各种操作。这些算法具有定义的执行策略(have a defined execution policy),决定它们如何执行以及如何与底层硬件交互。STL算法执行策略首先在C++17标准中引入。
C++17标准引入了三种新的执行策略:实例(instance)用于指定并行算法的执行策略
1.std::execution::sequenced_policy:实例std::execution::seq
该策略指定算法应按顺序执行,即没有并行化。当不指定执行策略时,算法将按顺序执行。使用这个选项和使用不接受执行策略参数的非并行化版本的效果类似。提供这个策略的目的是让你可以只修改一个参数来要求顺序执行,而不是换用一个签名不同的函数来做到这一点。
(1).优点:简单且可预测;避免数据竞争;适合小型任务,因为不存在并行开销
(2).缺点:对于大型任务效率不高
2.std::execution::parallel_policy:实例std::execution::par
该策略指定算法应并行执行,即使用多个线程。该标准没有指定应使用的线程数,但应该不止一个(你不能控制使用多少个线程)。
(1).优点:更快地执行更大的任务;多核系统的最佳使用
(2).缺点:可能会引入开销;由于这种开销,可能并不总是比顺序执行更快;可以引入竞争条件
3.std::execution::parallel_unsequenced_policy:实例std::execution::par_unseq
该策略指定算法应并行执行,并可能产生不确定的结果,即不保证处理元素的顺序。这些执行策略是使用硬件和软件机制(例如线程和SIMD指令)的组合来实现的,以优化算法的性能。
(1).优点:更快地执行重复操作;可以在带有矢量指令(vector instructions)的硬件上使用
(2).缺点:并不适合所有任务;可能并非所有硬件都支持
使用并行算法是很简单的:
(1).包含头文件<execution>
(2).像通常调用算法一样进行调用,只不过需要添加一个第一个参数std::execution::par或std::execution::par_unseq,这样我们就可以要求算法在并行模式下运行
适合使用并行算法的场景应该是:对每个元素的处理需要消耗很多的时间并且处理过程需要独立于其他元素的处理。
支持执行策略的C++算法的列表:https://www.geeksforgeeks.org/execution-policy-of-stl-algorithms-in-modern-cpp/
注意:
(1).并非所有算法都支持所有执行策略,并且某些算法根据所使用的执行策略可能具有不同的性能特征
(2).这些策略的可用性可能会根据所使用的C++标准的实现和版本而有所不同
(3).所有的并行算法要求迭代器至少是前向迭代器
(4).并行算法实际运行的方式是实现特定的。当然,使用多线程不一定能加快速度,因为启动和控制多线程也会消耗时间
(5).当处理元素的函数因为未捕获的异常而退出时所有的并行算法会调用std::terminate()
(6).并行算法本身也可能抛出异常。如果它们申请并行执行所需的临时内存资源时失败了,可能会抛出std::bad_alloc异常。然而,不会有别的异常被抛出
以下为测试代码:
namespace {
template<typename T>
inline void print(const std::vector<T>& vec)
{
std::cout << "result: ";
for (const auto& i : vec) {
std::cout << i << " ";
}
std::cout << "\n";
}
} // namespace
int test_parallel_stl()
{
// 1.std::execution::sequenced_policy
std::vector<int> vec1 = { 5, 2, 3, 1, 4 };
std::sort(std::execution::seq, vec1.begin(), vec1.end());
print(vec1); // result: 1 2 3 4 5
// 2.std::execution::parallel_policy
std::vector<int> vec2(5);
std::transform(std::execution::par, vec1.begin(), vec1.end(), vec2.begin(), [](int x) { return x * x; });
print(vec2); // result: 1 4 9 16 25
// 3.std::execution::parallel_unsequenced_policy
std::vector<int> vec3(5);
std::transform(std::execution::par_unseq, vec1.begin(), vec1.end(), vec3.begin(), [](int x) { return x * x; });
print(vec3); // result: 1 4 9 16 25
return 0;
}
执行结果如下图所示:
GitHub:https://github.com/fengbingchun/Messy_Test