How do I use the new C17 execution policies?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
C++17 added execution policies so standard algorithms can express whether work should run sequentially or may run in parallel. The feature is simple to call, but using it correctly requires understanding which algorithms support policies, what guarantees change, and why not every loop becomes safe just because par exists.
The Basic Idea
Execution policies live in std::execution and are passed as the first argument to supported algorithms.
The three main C++17 policies are:
- '
std::execution::seqfor normal sequential execution' - '
std::execution::parfor parallel execution' - '
std::execution::par_unseqfor parallel execution with possible vectorization'
The policy is a request to the implementation, not a guarantee of a specific threading strategy.
Using seq, par, and par_unseq
The easiest way to experiment is with an algorithm such as std::for_each or std::sort.
This may run iterations on multiple threads, but the lambda must still be safe when several invocations happen at once.
par_unseq is more aggressive. It permits both parallelism and unsequenced execution, which means the callable must be even more conservative about side effects.
Which Algorithms Support Policies
Only algorithms with execution-policy overloads can use this feature. Common examples include for_each, sort, transform, reduce, transform_reduce, and copy.
A typical numeric example is:
This is often a better example than for_each because reductions fit parallel execution naturally.
Rules for Safe Parallel Use
The most important rule is that your callable must not create data races.
This is bad code:
Multiple threads may update total at the same time, which is undefined behavior.
Use a reduction algorithm instead:
That expresses the operation in a way the library can parallelize safely.
Performance Expectations
Using par does not automatically make code faster. Parallel execution helps when the per-element work is large enough and independent enough to offset scheduling overhead.
For tiny inputs, sequential execution is often faster.
Real speedup also depends on the standard library implementation and toolchain. Some implementations support these overloads but provide limited or backend-dependent parallelism.
Build and Toolchain Notes
You need a compiler and standard library with execution policy support, plus a C++17 build mode.
A typical compile command looks like:
If #include <execution> compiles but performance does not change, the implementation may be falling back to sequential behavior for that environment.
Common Pitfalls
A common mistake is using std::execution::par with a lambda that writes to shared state such as a counter, log buffer, or shared container.
Another pitfall is assuming algorithms preserve element order the same way once parallel execution is allowed. Some algorithms still guarantee specific results, but the timing and scheduling of individual calls are no longer something you should depend on.
Developers also sometimes use par_unseq with code that performs locking, I/O, or other side effects. That policy is intended for very restricted, vectorization-friendly work.
Finally, benchmark before and after. Execution policies are a tool, not a blanket optimization switch.
Summary
- Pass an execution policy such as
std::execution::paras the first argument to supported algorithms. - Use
seqfor normal behavior,parfor parallel work, andpar_unseqfor the most permissive execution model. - Make sure the callable is free of data races and unsafe shared-state updates.
- Prefer algorithms such as
reducewhen the operation is naturally parallel. - Expect results to depend on input size, algorithm choice, and library implementation support.
Related reading
- How do nicely concat asynchronous network requests in Qt
- How do you declare an interface in C++?
- How do you pass a function as a parameter in C?
- How does one transfer CUDA constant memory in tensorflow's C API
- How does stdsort work for list of pairs?
- How is nth_element Implemented?
- How is the new asynchronous model in C26 different from existing models?
- How is vectorvectorint heavier than vectorpairint,int?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.