C++17 stdpar¶
Learning Objectives
Explain the three C++17 execution policies:
seq,par,par_unseqUse
std::transformwith a parallel execution policy for the Stream TriadCompile for GPU execution with NVIDIA’s
nvc++and-stdpar=gpuCompare
std::parto explicit OpenMP and CUDA implementations
Standard Parallel Algorithms¶
C++17 added execution policies to most <algorithm> functions. The policy is passed as the first argument and tells the implementation how it may schedule work:
Policy |
Meaning |
|---|---|
|
Sequential, in-order — identical to pre-C++17 algorithms |
|
Parallel, may execute on multiple threads; order unspecified |
|
Parallel and vectorized; may interleave within a thread (SIMD) |
These apply to algorithms: std::transform, std::reduce, std::sort, std::for_each, std::fill, and others.
Note
On CPU, par typically dispatches to Intel’s libTBB or an OpenMP thread pool. With NVIDIA’s nvc++ compiler and -stdpar=gpu, the same par policy compiles to CUDA kernels with no source changes.
Stream Triad with std::transform¶
#include <algorithm>
#include <execution>
#include <vector>
void vector_operation(std::vector<double>& c,
const std::vector<double>& a,
const std::vector<double>& b,
double scalar) {
std::transform(std::execution::par,
a.begin(), a.end(),
b.begin(),
c.begin(),
[scalar](double a_val, double b_val) {
return a_val + scalar * b_val;
});
}
Swapping par for seq or par_unseq changes the parallelism strategy. When compiled with nvc++ -stdpar=gpu, par becomes a GPU kernel automatically.
Build Flags¶
# GCC with OpenMP
g++ -std=c++17 -O3 -fopenmp triad.cc -o triad
nvc++ -std=c++17 -stdpar=gpu -O3 triad.cc -o triad_gpu
-stdpar=gpu routes std::execution::par to CUDA. Memory management is handled transparently via CUDA Unified Memory.
module load nvhpc
nvc++ -std=c++17 -stdpar=gpu -O3 triad.cc -o triad_gpu
sbatch run.slurm
Comparison to Other Approaches¶
Approach |
Code complexity |
Portability |
Typical overhead |
|---|---|---|---|
CUDA |
High (explicit kernels) |
NVIDIA only |
Low |
OpenMP |
Medium (directives) |
Multi-vendor |
Low |
|
Low (standard library) |
Compiler-dependent |
Varies |
Running on ARC Clusters¶
For std::par GPU builds:
Load NVIDIA HPC SDK:
module load nvhpcRequest GPU:
#SBATCH --gres=gpu:1Compile and submit:
nvc++ -std=c++17 -stdpar=gpu triad.cc -o triad sbatch run.slurm
See GPU Usage for available modules and partitions.