Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
quickly thrown together parallel_for.h
#pragma once
#include <thread>
#include <mutex>
#include <algorithm>
//
// my sketchy parallel_for
// use:
//
// parallel_for(your_container, [&](auto & i)
// {
// remember to use a critical section around your result collection
// dont change the container or its contents in the loop
// return false == break - but be warned you only break out of one chunk
// return true == continue
// });
//
template< typename Container, typename Func >
void parallel_for(const Container& c, Func f)
{
if (!c.empty())
{
const size_t nthreads = std::min<size_t>(
c.size(),
std::thread::hardware_concurrency()
);
std::thread threads[nthreads-1];
auto loop = [&]
(typename Container::const_iterator first, typename Container::const_iterator last)
{
// loop over subset of items
for(auto i = first; i!=last; i++)
{
if (!f(i)) break;
}
};
auto itr = c.begin();
if (nthreads>1)
{
// divide work int chunks over n cores (including this one)
const int chunksize = c.size()/nthreads;
const int remainder = c.size()%nthreads;
// kick of threads for all other cores
int t = 0;
for(;t<remainder;t++)
{
auto first = itr;
std::advance(itr, chunksize+1);
threads[t] = std::thread(std::bind(loop, first, itr));
}
for(;t<nthreads-1;t++)
{
auto first = itr;
std::advance(itr, chunksize);
threads[t] = std::thread(std::bind(loop, first, itr));
}
assert(std::distance(itr ,c.end())>=1);
assert(std::distance(itr ,c.end())<=chunksize);
}
// finish in current thread
loop(itr ,c.end());
// wait for all the other threads to complete
for(auto& x : threads)
{
x.join();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment