From e15996db529b594d53a72513442ba83456bdbf76 Mon Sep 17 00:00:00 2001 From: nihonium Date: Sat, 13 May 2023 22:13:30 +0300 Subject: [PATCH] parallel max iterators --- .../01problem_paralel_max_iterators.cpp | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 term2/seminar01_thread/01problem_paralel_max_iterators.cpp diff --git a/term2/seminar01_thread/01problem_paralel_max_iterators.cpp b/term2/seminar01_thread/01problem_paralel_max_iterators.cpp new file mode 100644 index 0000000..8002471 --- /dev/null +++ b/term2/seminar01_thread/01problem_paralel_max_iterators.cpp @@ -0,0 +1,110 @@ +/* + Задача: + + В данном примере написана функция шаблонная getMax, которая находит максимум из чисел в некотором контейнере. + При этом вычисления проходят однопоточно. + + + Вам нужно написать шаблонную функцию + + template + RandIt getMax(int n, RandIt start, RandIt finish) + + которая будет делать то же самое, но только использовать для этого n потоков. + Функция должна принимать на вход количество потоков и два итератора, задающих + диапазон на котором нужно искать максимум. + Известно, что оба итератора являются random access итераторами. + + + + Проверить, что эта функция будет работать и для других контейнеров и типов хранящихся в них данных. + Например, для: + + std::deque d {1.2, 5.1, 8.2, 1.0, 0.2, 5.0, 7.8}; +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using std::cout, std::endl, std::size_t; +using namespace std::chrono_literals; + + +template +RandIt getMax(RandIt start, RandIt finish) +{ + RandIt maxIt = start; + for (auto it = start; it != finish; ++it) + { + if (*it > *maxIt) + maxIt = it; + } + return maxIt; +} + +template +struct maxBlock { + void operator() (RandIt first, RandIt last, RandIt& res) { + res = getMax(first, last); + } +}; + +template +RandIt getMax(int n, RandIt start, RandIt finish) { + std::vector results(n); + + std::vector threads(n - 1); + unsigned long const block_size = std::distance(start, finish) / n; + + RandIt block_start = start; + + for (int i = 0; i < n - 1; ++i) { + RandIt block_end = block_start; + std::advance(block_end, block_size); + threads[i] = std::thread(maxBlock(), + block_start, block_end, std::ref(results[i])); + block_start = block_end; + } + maxBlock() (block_start, finish, results[n - 1]); + + std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join)); + + return *getMax(results.begin(), results.end()); +} + +int main() +{ + cout << "Generating numbers!" << endl; + std::deque numbers; + + numbers.push_back(1); + + for (size_t i = 0; i < 1e7; ++i) + { + numbers.push_back(numbers.back() + 1); + } + + cout << "Numbers generated!" << endl; + + auto start = std::chrono::high_resolution_clock::now(); + auto it = getMax(numbers.begin(), numbers.end()); + cout << "Maximum = " << *it << endl; + auto end = std::chrono::high_resolution_clock::now(); + cout << "Time to calclulate max = " << std::chrono::duration_cast(end - start).count() + << " milliseconds." << endl; + + + start = std::chrono::high_resolution_clock::now(); + it = getMax(4, numbers.begin(), numbers.end()); + cout << "Maximum = " << *it << endl; + end = std::chrono::high_resolution_clock::now(); + cout << "Time to calclulate max = " << std::chrono::duration_cast(end - start).count() + << " milliseconds." << endl; +}