zoukankan      html  css  js  c++  java
  • 异常安全的并行 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;
    }
  • 相关阅读:
    HZNU 2019 Summer training 6
    HZNU 2019 Summer training 5
    HZNU 2019 Summer training 4
    Garlands CodeForces
    HZNU 2019 Summer training 3
    UVA
    HZNU 2019 Summer training 2
    Serge and Dining Room(线段树)
    HZNU 2019 Summer training 1
    【7-10 PAT】树的遍历
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4907266.html
Copyright © 2011-2022 走看看