Question

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).

Était-ce utile?

La solution

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.

Autres conseils

The following will allow you to pass a handle that returns an int or double (or other numeric type) to your function. The function will return whatever type is returned by your handle. You should be mindful of overflows however.

template<typename L>
inline L Graph::parallelSumForNodes(std::function<L(node)> handle) {
    L sum = 0;
#pragma omp parallel for reduction(+:sum)
    for (node v = 0; v < z; ++v) {
        // call here
        if (exists[v]) {
            sum += handle(v);
        }
    }
    return sum;
}

Specify your template parameter to define the return type of std::function:

template<typename L>
inline L Graph::parallelSumForNodes(std::function<L(node)> handle)
{
    L sum();
    ...
    return( sum );
{
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top