c++++17的execution_policy使用需注意四点:一、选择合适策略,seq用于顺序执行,par允许多线程并行,par_unseq支持并行+向量化;二、任务需满足大数据量、计算密集型才适合并行,小任务反而变慢;三、确保函数无副作用,避免共享变量竞争,可用原子操作或归约算法;四、不同编译器实现有差异,需查文档并做性能测试。

并行算法在C++17中引入了
execution_policy,让标准库算法支持并行执行。但很多人用的时候容易出错,或者没发挥出性能优势。关键点在于:根据任务特性选择合适的策略,而不是随便加个
par就完事。

下面几个常见场景和注意事项,帮你正确使用STL的并行策略。

一、了解三种基本执行策略
C++标准提供了三种基础执行策略:
std::execution::seq
:顺序执行,不并行std::execution::par
:允许并行执行(共享内存线程池)std::execution::par_unseq
:允许并行+向量化执行(可能跨核+SIMD)
选哪个?看你要处理的任务能不能安全地拆分到多个线程,并且是否能利用SIMD指令加速。

举个例子:
std::vectordata = get_big_data(); std::sort(std::execution::par, data.begin(), data.end());
这行代码会让排序操作尝试用多线程完成,适用于大数据量、计算密集型任务。
二、别盲目用par
,先判断任务是否值得并行
不是所有算法用了
par就会变快。小数据量、轻量级操作反而可能因为线程调度开销而变慢。
比如:
std::for_each(std::execution::par, vec.begin(), vec.end(), [](int& x) { x += 1; });如果vec只有几十个元素,这个并行操作很可能比串行还慢。
建议:
- 数据量大(比如几万条以上)
- 每个元素的操作较重(比如有函数调用、IO、复杂计算)
- CPU核心数较多时(4核以上更明显)
才考虑使用
par或
par_unseq。
三、注意线程安全和副作用问题
并行算法要求传入的函数对象必须是“无副作用”的,否则行为未定义。
比如下面这个写法就有风险:
int count = 0;
std::for_each(std::execution::par, vec.begin(), vec.end(), [&](int x) {
if (x > 0) ++count;
});多个线程同时修改
count变量,没有同步机制,结果不可预测。
解决办法:
- 使用原子变量(如
std::atomic
) - 或者改用
transform_reduce
等归约类算法来合并结果
四、不同平台实现差异要留意
虽然C++标准规定了接口,但不同编译器对并行策略的支持程度不一样。
比如:
- MSVC 的PPL实现比较早也比较稳定
- GCC 从9开始支持,但某些算法仍为串行实现
- Clang支持情况取决于所用的标准库(如libc++或libstdc++)
所以你写的代码在一台机器上跑得飞快,在另一台却没效果,很可能是底层实现的问题。
建议做法:
- 查阅你使用的编译器文档确认支持情况
- 对关键路径做性能测试
- 不要假设“写了par就一定并行”
基本上就这些。选好策略、控制粒度、注意并发安全,才能真正把并行算法用起来。










