Добрый день. Нужно реализовать обработку контейнеров в нескольких потоках. Набросал на коленке простой тестовый пример, но он работает не так, как ожидалось:
#include <cmath>
#include <vector>
#include <thread>
#include <iostream>
#include <functional>
int test(int x)
{
return x * x;
}
void print(const std::vector<int>& v)
{
for (const auto i : v)
{
std::cout << i << " ";
}
std::cout << std::endl;
}
void print(std::vector<int>::iterator begin, std::vector<int>::iterator end)
{
auto it = begin;
while (it != end)
{
std::cout << *it << " ";
++it;
}
std::cout << std::endl;
}
std::vector<int>::iterator for_each(std::vector<int>::iterator first, std::vector<int>::iterator last,
std::vector<int>::iterator result, const std::function<int(int)>& mapFunctor)
{
while (first != last)
{
*result = mapFunctor(*first);
++result;
++first;
}
return result;
}
std::vector<int>::iterator mapped(std::vector<int>::iterator first, std::vector<int>::iterator last,
std::vector<int>::iterator result, const std::function<int(int)>& mapFunctor)
{
auto availableThreads = std::thread::hardware_concurrency();
if (availableThreads < 2)
{
for_each(first, last, result, mapFunctor);
}
else
{
const auto totalSize = std::distance(first, last);
const auto blockSize = static_cast<size_t>(std::ceil(1.0 * totalSize / availableThreads));
std::vector<std::thread> threads;
std::vector<std::vector<int>> results;
auto current = first;
for (unsigned int i = 0; i < (availableThreads - 1); ++i)
{
auto blockStart = current;
auto blockEnd = blockStart;
std::advance(blockEnd, blockSize);
current = blockEnd;
results.emplace_back(std::vector<int>(blockSize));
threads.emplace_back(
std::thread(for_each, std::ref(blockStart),
std::ref(blockEnd), results.at(i).begin(), mapFunctor));
}
result = for_each(current, last, result, mapFunctor);
for (unsigned int i = 0; i < threads.size(); ++i)
{
if (threads[i].joinable())
{
threads[i].join();
}
print(results.at(i));
result = std::copy(results.at(i).begin(), results.at(i).end(), result);
}
}
return result;
}
int main()
{
std::vector<int> v;
for (unsigned int i = 1; i < 41; ++i)
{
v.emplace_back(i);
}
std::vector<int> v2;
v2.resize(v.size());
print(v);
mapped(v.begin(), v.end(), v2.begin(), test);
print(v2);
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
121 144 169 196 225
121 144 169 196 225
961 1024 1089 1156 1225
676 729 784 841 900
961 1024 1089 1156 1225
961 1024 1089 1156 1225
961 1024 1089 1156 1225
1296 1369 1444 1521 1600 121 144 169 196 225 121 144 169 196 225 961 1024 1089 1156 1225 676 729 784 841 900 961 1024 1089 1156 1225 961 1024 1089 1156 1225 961 1024 1089 1156 1225