并行却并不高效的 find

template<typename Iterator, typename MatchType>
Iterator parallelFind(Iterator first, Iterator last, MatchType match)
{
    struct FindElement
    {
        void operator()(Iterator begin, Iterator end,
                        MatchType match,
                        std::promise<Iterator>* result,
                        std::atomic<bool>*      isFound)
        {
            try {
                for (; begin != end; ++begin)
                {
                    if (*begin == match)
                    {
                        result->set_value(begin);
                        isFound->store(true);
                        return;
                    }
                }
            } catch (...) {
                try {
                    result->set_exception(std::current_exception());
                    isFound->store(true);
                } catch (...)
                {}
            }
        }
    };
    
    size_t const length = std::distance(first, last);
    if (length == 0)
    {
        return last;
    }
    
    size_t constexpr minDataPerThread  = 25;
    size_t const     hardwareThreadNum = std::thread::hardware_concurrency();
    size_t const     neededThreadNum   =
        (length + minDataPerThread - 1) / minDataPerThread;
    size_t const     threadNum         = std::min(neededThreadNum,
                                                  hardwareThreadNum != 0
                                                  ? hardwareThreadNum
                                                  : 2);
    size_t const blockSize             = length / threadNum;
    std::vector<std::thread>       threads(threadNum - 1);
    std::atomic<bool>              isFound(false);
    std::promise<Iterator> result;
    {
        ThreadsJoiner joiner(threads);
        auto blockBegin = first;
        for (size_t i = 0; i < (threadNum - 1); ++i)
        {
            auto  blockEnd = blockBegin;
            std::advance(blockEnd, blockSize);
            threads[i] = std::thread(FindElement(),
                                     blockBegin, blockEnd, match,
                                     &result, &isFound);
            blockBegin = blockEnd;
        }
        
        FindElement()(blockBegin, last, match, &result, &isFound);
    }
    if (!isFound.load())
    {
        return last;
    }
    return result.get_future().get();
}

template <typename Iterator, typename MatchType>
Iterator ImplParallelFind(Iterator first, Iterator last, MatchType match,
                          std::atomic<bool>& is_found)
{
    try {
        size_t const            length              = std::distance(first, last);
        static size_t constexpr min_data_per_thread = 25;
        if (length < (2 * min_data_per_thread)){
            // If result has found, break.
            for (; (first != last) && (!is_found.load()); ++first){
                if (*first == match){
                    is_found = true;
                    return first;
                }
            }
            return last;
        }else{
            auto const mid_iterator = first + (length / 2);
            auto async_result =
                std::async(&ImplParallelFind<Iterator, MatchType>,
                           mid_iterator, last, match, std::ref(is_found));
            auto const local_result = ImplParallelFind(first, mid_iterator,
                                                       match, is_found);
            return local_result == mid_iterator
            ? async_result.get()
            : local_result;
        }
    } catch (...) {
        is_found = true;
        throw;
    }
}

template <typename Iterator, typename MatchType>
Iterator ParallelFind(Iterator first, Iterator last, MatchType match) {
    std::atomic<bool> is_found(false);
    return ImplParallelFind(first, last, match, is_found);
}

 

posted @ 2015-11-04 14:20  wu_overflow  阅读(159)  评论(0编辑  收藏  举报