[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

| Functions and classes for parallel processing. |

## Classes

class | ParallelOptions
| Option base class for parallel algorithms. More...
class | ThreadPool
| Thread pool class to manage a set of parallel workers. More...

## Functions

template<class F >
threading::future< void > | enqueue (F &&f)
template<class F >
auto | enqueueReturning (F &&f) -> threading::future< decltype(f(0))>
template<... >
void | parallel_foreach (...)
| Apply a functor to all items in a range in parallel. More...
| ~ThreadPool ()

## Detailed Description

## Function Documentation

## ◆ parallel_foreach()

void vigra::parallel_foreach | ( |  | ... | ) |

Apply a functor to all items in a range in parallel.

Create a thread pool (or use an existing one) to apply the functor

- f to all items in the range `[begin, end)` in parallel.
- f must be callable with two arguments of type `size_t` and `T`, where the first argument is the thread index (starting at 0) and T is convertible from the iterator's `reference_type` (i.e. the result of `*begin`).

If the iterators are forward iterators (`std::forward_iterator_tag`), you can provide the optional argument `nItems` to avoid the a `std::distance(begin, end)` call to compute the range's length.

Parameter `nThreads` controls the number of threads. `parallel_foreach` will split the work into about three times as many parallel tasks. If `nThreads = ParallelOptions::Auto`, the number of threads is set to the machine default (`std::thread::hardware_concurrency()`).

If `nThreads = 0`, the function will not use threads, but will call the functor sequentially. This can also be enforced by setting the preprocessor flag `VIGRA_SINGLE_THREADED`, ignoring the value of `nThreads` (useful for debugging).

Declarations:

namespace vigra {
// pass the desired number of threads or ParallelOptions::Auto
// (creates an internal thread pool accordingly)
template<class ITER, class F>
void parallel_foreach(int64_t nThreads,
ITER begin, ITER end,
F && f,
const uint64_t nItems = 0);
// use an existing thread pool
template<class ITER, class F>
void parallel_foreach(ThreadPool & pool,
ITER begin, ITER end,
F && f,
const uint64_t nItems = 0);
// pass the integers from 0 ... (nItems-1) to the functor f,
// using the given number of threads or ParallelOptions::Auto
template<class F>
void parallel_foreach(int64_t nThreads,
uint64_t nItems,
F && f);
// likewise with an existing thread pool
template<class F>
void parallel_foreach(ThreadPool & threadpool,
uint64_t nItems,
F && f);
}

Usage:

#include <iostream>
#include <algorithm>
#include <vector>
#include <vigra/threadpool.hxx>
using namespace std;
using namespace vigra;
int main()
{
size_t const n_threads = 4;
size_t const n = 2000;
vector<int> input(n);
auto iter = input.begin(),
end = input.end();
// fill input with 0, 1, 2, ...
iota(iter, end, 0);
// compute the sum of the elements in the input vector.
// (each thread computes the partial sum of the items it sees
// and stores the sum at the appropriate index of 'results')
vector<int> results(n_threads, 0);
parallel_foreach(n_threads, iter, end,
// the functor to be executed, defined as a lambda function
// (first argument: thread ID, second argument: result of *iter)
[&results](size_t thread_id, int items)
{
results[thread_id] += items;
}
);
// collect the partial sums of all threads
int sum = accumulate(results.begin(), results.end(), 0);
cout << "The sum " << sum << " should be equal to " << (n*(n-1))/2 << endl;
}

## ◆ ~ThreadPool()

~ThreadPool | ( |  | ) |

The destructor joins all threads.

## ◆ enqueueReturning()

auto enqueueReturning | ( | F && | f | ) | -> threading::future<decltype(f(0))>

Enqueue a task that will be executed by the thread pool. The task result can be obtained using the get() function of the returned future. If the task throws an exception, it will be raised on the call to get().

## ◆ enqueue()

threading::future< void > enqueue | ( | F && | f | ) |

Enqueue function for tasks without return value. This is a special case of the enqueueReturning template function, but some compilers fail on `std::result_of<F(int)>::type` for void(int) functions.

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.11.0