Post

std::execution::par

std::execution::par

std::execution::par


Prerequisites


1. What is std::execution::par? (C++17 Parallel Execution)

C++17 introduced parallel algorithms through the <execution> header. std::execution::par is a policy that enables multi-threaded execution for standard algorithms.

It allows developers to write code in a familiar STL style while letting the standard library handle parallelization internally.

1
2
3
4
5
6
7
8
9
10
#include <algorithm>
#include <execution>
#include <vector>

std::vector<int> v = {1, 2, 3, 4, 5};

std::for_each(std::execution::par, v.begin(), v.end(), [](int& x)
{
    x *= 2;
});
1
{2, 4, 6, 8, 10}

2. How to work

1
std::execution::par

This single argument changes the execution model:

  • Sequential → Parallel
  • Single thread → Multiple threads
  • Manual thread management → Automatic
Conceptual Model

Internally, the algorithm may split work like this:

1
2
3
4
Thread 1 → v[0 ~ 249]
Thread 2 → v[250 ~ 499]
Thread 3 → v[500 ~ 749]
Thread 4 → v[750 ~ 999]

Each thread processes a different chunk independently.

Note: The actual implementation is library-dependent.

Supported Algorithms

Common algorithms that support par:

  • std::for_each
  • std::transform
  • std::sort
  • std::reduce
  • std::transform_reduce
  • std::inclusive_scan
  • std::exclusive_scan
Example: transform
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <algorithm>
#include <execution>
#include <vector>

std::vector<int> input = {1, 2, 3, 4, 5};
std::vector<int> output(input.size());

std::transform(std::execution::par,
               input.begin(), input.end(),
               output.begin(),
               [](int x)
               {
                   return x * x;
               });
Critical Rule: No Data Dependency

Parallel execution requires independent work per element.

3. Features

Safe
1
2
3
4
std::for_each(std::execution::par, v.begin(), v.end(), [](int& x)
{
    x *= 2;
});
  • No shared state
  • No dependency between elements
Unsafe (Race Condition)
1
2
3
4
5
6
int sum = 0;

std::for_each(std::execution::par, v.begin(), v.end(), [&](int x)
{
    sum += x;   // race condition
});
  • Multiple threads modify sum
  • Undefined behavior

Order is NOT Guaranteed

1
2
3
4
std::for_each(std::execution::par, v.begin(), v.end(), [](int x)
{
    std::cout << x << " ";
});

Output order may vary.

This post is licensed under CC BY 4.0 by the author.