Created
April 2, 2015 11:27
-
-
Save mfrischknecht/1f0c86a3249fb30e6d16 to your computer and use it in GitHub Desktop.
Simple parallel foreach and ranges example in C++11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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