Skip to content

Instantly share code, notes, and snippets.

@mfrischknecht
Created April 2, 2015 11:27
Show Gist options
  • Save mfrischknecht/1f0c86a3249fb30e6d16 to your computer and use it in GitHub Desktop.
Save mfrischknecht/1f0c86a3249fb30e6d16 to your computer and use it in GitHub Desktop.
Simple parallel foreach and ranges example in C++11
#include <algorithm>
#include <future>
template<class I, class F>
void parallel_for_each(I rangeStart, I rangeEnd, F callback, int numSegments = 0)
{
int numValues = std::distance(rangeStart,rangeEnd);
numSegments = numSegments > 0 ? numSegments : numValues;
int segmentSize = numValues/numSegments;
std::vector<std::future<void>> futures(numSegments);
int segment = 0;
for (auto &future: futures)
{
future = std::async(std::launch::async, [=,&callback](){
auto segmentStart = rangeStart + segment*segmentSize;
auto segmentEnd = segment+1 < numSegments ? rangeStart + (segment+1)*segmentSize : rangeEnd;
for (auto i = segmentStart; i != segmentEnd; ++i) callback(*i);
});
++segment;
}
for (auto &future: futures) future.wait();
}
template<class T, class F>
void parallel_for_each(T range, F callback, int numSegments)
{
parallel_for_each(std::begin(range), std::end(range), callback, numSegments);
}
namespace Range
{
class Iterator : public std::iterator<std::random_access_iterator_tag, int>
{
public:
Iterator (): _index(0) {}
Iterator (int i): _index(i) {}
Iterator (const Iterator &other) = default;
Iterator &operator = (const Iterator &) = default;
int operator * () const { return _index; }
Iterator &operator ++ () { _index++; return *this; }
Iterator operator ++ (int) { Iterator tmp(*this); _index++; return tmp; }
Iterator &operator -- () { _index--; return *this; }
Iterator operator -- (int) { Iterator tmp(*this); _index--; return tmp; }
bool operator == (const Iterator &other) const { return _index == other._index; }
bool operator != (const Iterator &other) const { return _index != other._index; }
Iterator &operator += (difference_type d) { _index += d; return *this; }
Iterator &operator -= (difference_type d) { _index -= d; return *this; }
Iterator operator + (difference_type d) const { return Iterator(_index+d); }
Iterator operator - (difference_type d) const { return Iterator(_index-d); }
int operator [] (difference_type d) const { return _index + d; }
bool operator < (const Iterator &other) const { return _index < other._index; }
bool operator > (const Iterator &other) const { return _index > other._index; }
bool operator <= (const Iterator &other) const { return _index <= other._index; }
bool operator >= (const Iterator &other) const { return _index >= other._index; }
difference_type operator - (const Iterator &other) const { return _index - other._index; }
private:
int _index;
};
template<int SIZE,int OFFSET = 0>
struct Static
{
Iterator begin() const { return Iterator(OFFSET); }
Iterator end() const { return Iterator(OFFSET+SIZE); }
};
class Dynamic
{
public:
Dynamic(int offset, int size):
_offset(offset),
_size(size)
{}
Dynamic(int size):
_offset(0),
_size(size)
{}
Dynamic(const Dynamic &other) = default;
Dynamic &operator=(const Dynamic &other) = default;
Iterator begin() const { return Iterator(_offset); }
Iterator end() const { return Iterator(_offset+_size); }
private:
int _offset;
int _size;
};
}
int main ()
{
#if 0
//Dynamic range
parallel_for_each(Range::Dynamic(1000), [](int a) {
printf("%d\n",a);
}, 10);
#elif 1
//Static range
parallel_for_each(Range::Static<1000>(), [](int a) {
printf("%d\n",a);
}, 10);
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment