并行却并不高效的 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);
}