异常安全的并行 accumulate

template<typename Iterator, typename T>
struct AccumulateBlock
{
    T operator()(Iterator first, Iterator last)
    {
        return std::accumulate(first, last, T());
    }
};

class ThreadsJoiner
{
private:
    std::vector<std::thread>& threads;
public:
    ThreadsJoiner(std::vector<std::thread>& threads_):
    threads(threads_)
    {}
    
    ~ThreadsJoiner()
    {
        for (auto& thread : threads){
            if (thread.joinable()){
                thread.join();
            }
        }
    }
};

template<typename Iterator, typename T>
T parallelAccumulate(Iterator first, Iterator last, T init)
{
    size_t const     length              = std::distance(first, last);
    if (length == 0){
        return init;
    }
    
    size_t constexpr minDataNumPerThread = 25;
    size_t const     hardwareThreadNum   = std::thread::hardware_concurrency();
    size_t const     neededThreadNum     =
        ((length + minDataNumPerThread) / minDataNumPerThread);
    size_t const     threadNum           = std::min(neededThreadNum,
                                          (hardwareThreadNum == 0
                                           ? 2
                                           : hardwareThreadNum));
    size_t const     blockSize           = (length / threadNum);
    
    std::vector<std::future<T>> futures(threadNum - 1);
    std::vector<std::thread>    threads(threadNum - 1);
    ThreadsJoiner joiner(threads);
    
    auto blockBegin = first;
    for (size_t i = 0; i < (threadNum - 1); ++i){
        auto blockEnd = blockBegin;
        std::advance(blockEnd, blockSize);
        std::packaged_task<T(Iterator, Iterator)> task(
            (AccumulateBlock<Iterator, T>())
        );
        futures[i] = task.get_future();
        threads[i] = std::thread(std::move(task), blockBegin, blockEnd);
        blockBegin = blockEnd;
    }
    
    T lastResult = AccumulateBlock<Iterator, T>()(blockBegin, last);
    
    T result = init;
    for (auto& future : futures)
    {
        result += future.get();
    }
    result += lastResult;
    return result;
}

 

posted @ 2015-10-24 17:57  wu_overflow  阅读(151)  评论(0编辑  收藏  举报