cpp17 · advanced

C++17: Parallel STL Algorithms

C++17 adds an optional execution-policy first argument to roughly seventy STL algorithms: std::execution::seq runs sequentially and in order, par distributes work across threads, and par_unseq additionally permits SIMD vectorization and may interleave element processing within a thread. Opting in is as simple as passing the policy; the library owns the thread management. The cost is correctness obligations on your callables: under par they must be free of data races (no unsynchronized shared mutation), and under par_unseq they must also be vectorization-safe — no locks, mutexes, allocation, or blocking calls, since intra-thread interleaving can otherwise deadlock. Parallel reductions require std::reduce or std::transform_reduce rather than std::accumulate (which is defined as strictly left-to-right), and because reduce reorders and regroups, the combining operation must be associative and commutative, which can make floating-point results differ slightly. Parallelism only pays off for large inputs with meaningful per-element work, so benchmark; some standard libraries also require linking Intel TBB for the parallel backends.

🔑 Key line

C++17 parallel STL: pass std::execution::seq/par/par_unseq to ~70 algorithms to opt into threading/SIMD; callables must be race-free (par_unseq also lock/alloc-free), use std::reduce (associative+commutative) not accumulate, and profile — small N loses to overhead.

The code

#include <algorithm>
#include <execution>
std::sort(std::execution::par, v.begin(), v.end()); // parallel
std::for_each(std::execution::par_unseq, v.begin(), v.end(),
[](auto& x) { x = heavy(x); }); // par + vectorize
auto s = std::reduce(std::execution::par, v.begin(), v.end()); // not accumulate!
std::transform(std::execution::seq, ...); // explicit sequential

What this lesson walks through

  1. 01An execution policy splits the work
  2. 02Your callable must be safe to parallelize
  3. 03reduce, not accumulate
  4. 04When parallel actually pays

Pass std::execution::par as the first argument and the algorithm fans the range across CPU cores. par_unseq also vectorizes; seq forces sequential. One argument, parallel speedup.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of C++17: Parallel STL Algorithms and 100+ animated C++ interview lessons.

← Previous
C++17: std::filesystem
Next →
C++17: [[nodiscard]], [[maybe_unused]], [[fallthrough]]