How to: Convert an OpenMP parallel for Loop to Use the Concurrency Runtime
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
This example demonstrates how to convert a basic loop that uses the OpenMP parallel and for directives to use the Concurrency Runtime concurrency::parallel_for algorithm.
Example
This example uses both OpenMP and the Concurrency Runtime to compute the count of prime numbers in an array of random values.
// concrt-omp-count-primes.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <random>
#include <array>
#include <iostream>
using namespace concurrency;
using namespace std;
// Determines whether the input value is prime.
bool is_prime(int n)
{
if (n < 2)
return false;
for (int i = 2; i < n; ++i)
{
if ((n % i) == 0)
return false;
}
return true;
}
// Uses OpenMP to compute the count of prime numbers in an array.
void omp_count_primes(int* a, size_t size)
{
if (size == 0)
return;
size_t count = 0;
#pragma omp parallel for
for (int i = 0; i < static_cast<int>(size); ++i)
{
if (is_prime(a[i])) {
#pragma omp atomic
++count;
}
}
wcout << L"found " << count
<< L" prime numbers." << endl;
}
// Uses the Concurrency Runtime to compute the count of prime numbers in an array.
void concrt_count_primes(int* a, size_t size)
{
if (size == 0)
return;
combinable<size_t> counts;
parallel_for<size_t>(0, size, [&](size_t i)
{
if (is_prime(a[i])) {
counts.local()++;
}
});
wcout << L"found " << counts.combine(plus<size_t>())
<< L" prime numbers." << endl;
}
int wmain()
{
// The length of the array.
const size_t size = 1000000;
// Create an array and initialize it with random values.
int* a = new int[size];
mt19937 gen(42);
for (size_t i = 0; i < size; ++i) {
a[i] = gen();
}
// Count prime numbers by using OpenMP and the Concurrency Runtime.
wcout << L"Using OpenMP..." << endl;
omp_count_primes(a, size);
wcout << L"Using the Concurrency Runtime..." << endl;
concrt_count_primes(a, size);
delete[] a;
}
This example produces the following output.
Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.
The parallel_for
algorithm and OpenMP 3.0 allow for the index type to be a signed integral type or an unsigned integral type. The parallel_for
algorithm also makes sure that the specified range does not overflow a signed type. OpenMP versions 2.0 and 2.5 allow for signed integral index types only. OpenMP also does not validate the index range.
The version of this example that uses the Concurrency Runtime also uses a concurrency::combinable object in place of the atomic directive to increment the counter value without requiring synchronization.
For more information about parallel_for
and other parallel algorithms, see Parallel Algorithms. For more information about the combinable
class, see Parallel Containers and Objects.
Example
This example modifies the previous one to act on an std::array object instead of on a native array. Because OpenMP versions 2.0 and 2.5 allow for signed integral index types only in a parallel``for
construct, you cannot use iterators to access the elements of a Standard Template Library (STL) container in parallel. The Parallel Patterns Library (PPL) provides the concurrency::parallel_for_each algorithm, which performs tasks, in parallel, on an iterative container such as those provided by the STL. It uses the same partitioning logic that the parallel_for
algorithm uses. The parallel_for_each
algorithm resembles the STL std::for_each algorithm, except that the parallel_for_each
algorithm executes the tasks concurrently.
// Uses OpenMP to compute the count of prime numbers in an
// array object.
template<size_t Size>
void omp_count_primes(const array<int, Size>& a)
{
if (a.size() == 0)
return;
size_t count = 0;
int size = static_cast<int>(a.size());
#pragma omp parallel for
for (int i = 0; i < size; ++i)
{
if (is_prime(a[i])) {
#pragma omp atomic
++count;
}
}
wcout << L"found " << count
<< L" prime numbers." << endl;
}
// Uses the Concurrency Runtime to compute the count of prime numbers in an
// array object.
template<size_t Size>
void concrt_count_primes(const array<int, Size>& a)
{
if (a.size() == 0)
return;
combinable<size_t> counts;
parallel_for_each(begin(a), end(a), [&counts](int n)
{
if (is_prime(n)) {
counts.local()++;
}
});
wcout << L"found " << counts.combine(plus<size_t>())
<< L" prime numbers." << endl;
}
Compiling the Code
Copy the example code and paste it in a Visual Studio project, or paste it in a file that is named concrt-omp-count-primes.cpp
and then run the following command in a Visual Studio Command Prompt window.
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp
See Also
Migrating from OpenMP to the Concurrency Runtime
Parallel Algorithms
Parallel Containers and Objects