My graph data structure for parallel algorithms has the following iterator method:
/**
* Iterate in parallel over all nodes of the graph and call handler (lambda closure).
*/
void Graph::parallelForNodes(std::function<void(node)> handle) {
#pragma omp parallel for
for (node v = 0; v < z; ++v) {
// call here
handle(v);
}
}
I could have declared the handle
function as a template parameter, but I thought the preferred way in C++11 is to use std::function
.
Now I want to perform a parallel reduction using OpenMP with such an iterator. The return values of each call to handle
are reduced to a sum. With function templates, this looks like:
template<typename L>
inline double Graph::parallelSumForNodes(L handle) {
double sum = 0.0;
#pragma omp parallel for reduction(+:sum)
for (node v = 0; v < z; ++v) {
// call here
if (exists[v]) {
sum += handle(v);
}
}
return sum;
}
What is the equivalent using std::function
? Can I define the type of handle
to return double or int (because the body of the function works with both).
Perhaps a two parameter member function, along the lines of std::accumulate
?
template<typename Handle, typename Accumulator>
Accumulator Graph::parallelSumForNodes(Handle handle, Accumulator sum)
{
#pragma omp parallel for reduction(+:sum)
for (node v = 0; v < z; ++v) {
// call here
if (exists[v]) {
sum += handle(v);
}
}
return sum;
}
Note that this has the same caveat as std::accumulate
: you have to be careful with the type of the accumulator you pass it.