-
Notifications
You must be signed in to change notification settings - Fork 80
Курпяков Алексей. Технология SEQ-MPI. Сумма элементов вектора. Вариант 1 #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
allnes
merged 21 commits into
learning-process:master
from
AlKurpiakov:kurpiakov_a_elem_vec_sum
Dec 10, 2025
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b285b23
Add files via upload
AlKurpiakov 32adcde
Merge branch 'learning-process:master' into pre_commit
AlKurpiakov ed78441
Merge branch 'learning-process:master' into pre_commit
AlKurpiakov 6e82533
fix clang-format/tidy
AlKurpiakov cbd848e
fix clang-format/tidy
AlKurpiakov df9f99b
fix clang-format/tidy
AlKurpiakov 18fbe4e
fix ctidy
AlKurpiakov 3707623
fix ctidy
AlKurpiakov e414fac
fix ctidy
AlKurpiakov ed029c8
fix ctidy
AlKurpiakov 8acf029
fix ctidy
AlKurpiakov 7635c79
fix ctidy
AlKurpiakov 5978909
fix bugs + make a report
AlKurpiakov f88bc90
fix bugs + make a report
AlKurpiakov 6b142b2
finalize report
AlKurpiakov 4e2ad69
fix ctidy
AlKurpiakov afd4273
fix ctidy
AlKurpiakov 46615fb
fix ctidy
AlKurpiakov 42553c7
fix ctidy
AlKurpiakov d8a99bc
fix ctidy
AlKurpiakov 6c04eb2
fix ctidy
AlKurpiakov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| #include <string> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
| using InType = std::tuple<int, std::vector<int>>; | ||
|
allnes marked this conversation as resolved.
|
||
| using OutType = int64_t; | ||
| using TestType = std::tuple<InType, std::string, OutType>; | ||
| using BaseTask = ppc::task::Task<InType, OutType>; | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "student": { | ||
| "first_name": "Алексей", | ||
| "last_name": "Курпяков", | ||
| "middle_name": "Георгиевич", | ||
| "group_number": "3823Б1ФИ3", | ||
| "task_number": "1" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #pragma once | ||
|
|
||
| #include "kurpiakov_a_elem_vec_sum/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
| class KurpiakovAElemVecSumMPI : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kMPI; | ||
| } | ||
| explicit KurpiakovAElemVecSumMPI(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| #include "kurpiakov_a_elem_vec_sum/mpi/include/ops_mpi.hpp" | ||
|
|
||
| #include <mpi.h> | ||
|
|
||
| #include <cmath> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "kurpiakov_a_elem_vec_sum/common/include/common.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
|
|
||
| KurpiakovAElemVecSumMPI::KurpiakovAElemVecSumMPI(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumMPI::ValidationImpl() { | ||
| bool res = (GetOutput() == 0) && (std::cmp_equal((std::get<1>(GetInput()).size()), std::get<0>(GetInput()))); | ||
| return res; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumMPI::PreProcessingImpl() { | ||
| GetOutput() = 0; | ||
| return true; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumMPI::RunImpl() { | ||
| int rank = 0; | ||
| int size = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &size); | ||
|
|
||
| int total_size = 0; | ||
| if (rank == 0) { | ||
| total_size = std::get<0>(GetInput()); | ||
| } | ||
|
|
||
| MPI_Bcast(&total_size, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| if (total_size == 0) { | ||
| GetOutput() = 0LL; | ||
| return true; | ||
| } | ||
|
|
||
| std::vector<int> batch(size); | ||
| std::vector<int> displs(size); | ||
| int batch_size = total_size / size; | ||
| int remainder = total_size % size; | ||
| for (int i = 0; i < size; ++i) { | ||
| batch[i] = batch_size + (i < remainder ? 1 : 0); | ||
| displs[i] = (i == 0) ? 0 : displs[i - 1] + batch[i - 1]; | ||
| } | ||
|
|
||
| int local_size = batch[rank]; | ||
| std::vector<int> local_data(local_size); | ||
|
|
||
| int *sendbuf = nullptr; | ||
| if (rank == 0) { | ||
| sendbuf = const_cast<int *>(std::get<1>(GetInput()).data()); | ||
| } | ||
|
|
||
| MPI_Scatterv(sendbuf, batch.data(), displs.data(), MPI_INT, local_data.data(), local_size, MPI_INT, 0, | ||
| MPI_COMM_WORLD); | ||
|
|
||
| OutType local_sum = 0LL; | ||
| for (int i = 0; i < local_size; ++i) { | ||
| local_sum += static_cast<OutType>(local_data[i]); | ||
| } | ||
|
|
||
| OutType global_sum = 0LL; | ||
| MPI_Reduce(&local_sum, &global_sum, 1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD); | ||
|
|
||
| MPI_Bcast(&global_sum, 1, MPI_LONG_LONG, 0, MPI_COMM_WORLD); | ||
|
|
||
| GetOutput() = global_sum; | ||
|
|
||
| MPI_Barrier(MPI_COMM_WORLD); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumMPI::PostProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| # Сумма элементов вектора | ||
|
|
||
| - Студент: Курпяков Алексей Георгиевич, 3823Б1ФИ3 | ||
| - Технологии: SEQ | MPI | ||
| - Вариант: 1 | ||
|
|
||
| ## 1. Введение | ||
| В рамках данной работы был реализован алгоритм суммирования элементов вектора: последовательна и параллельная реализация. | ||
|
|
||
| ## 2. Постановка задачи | ||
| Дан вектор v из N элементов. Необходимо найти найти сумму всех его элементов. | ||
| Рассмотрим элементы v = {1, 2, 3 ... N} | ||
| Решением задачи будет нахождения суммы: sum = v[0] + v[1] + ... + v[N - 1] | ||
|
|
||
| ## 3. Описание линейного алгоритма | ||
|
|
||
| Последовательная версия: | ||
| проходимся по всему массиву, собираем префикс сумму по нему. | ||
|
|
||
|
|
||
| ## 4. Описание схемы параллельного алгоритма | ||
| Пусть у нас K процессов, вектор размера N, тогда алгоритм такой: | ||
| Процессы делят массив на M частей. | ||
| Части выделяются следующим образом: | ||
| Сначала считаем минимум, который будет каждый процесс обрабатывать: | ||
| batch = N/K | ||
| Затем вычисляем остаток от деления: | ||
| remainder = M % N | ||
| Первые remainder процессов заберут по 1 элементу из массива, остальные отработают только свой пакет. | ||
| Затем 0-ой процесс рассылает каждому потоку свой участок памяти и его размер остальным процессам. | ||
| После того как каждый процесс отработал свой участок и посчитал сумму внутри своего вектора 0-ой процесс собрает результаты и суммирует их. | ||
|
|
||
| ## 5. Окружение | ||
| - Hardware/OS: CPU - AMD Rizen 7 7840HS, cores - 8, RAM - 16GB, Ubuntu 24 on WSL | ||
| - Toolchain: GCC 13, Release | ||
| - Environment: PPC_NUM_PROC = 8 | ||
| - Data: |v| = 10000000, v[i] = i | ||
|
|
||
| ## 6. Результаты экспериментов и выводы | ||
|
|
||
| Функциональные тесты содержат 9 тестов: | ||
| - Тест1: пустой вектор | ||
| - Тест2: одиночный элемент | ||
| - Тест3: положительные числа в векторе | ||
| - Тест4: вектор состоящий из нулей | ||
| - Тест5: значения с разными знаками | ||
| - Тест6: значения граничащие с переполнением типа int | ||
| - Тест7: переполнение типа int | ||
| - Тест8: только отрицательные числа | ||
| - Тест9: вектор четной длины, такой что для любого v[i] существует v[j] = -v[i] (i != j) | ||
|
|
||
| Тест на производительность - |v| = {5000000, 7500000 10000000}, v[i] = i | ||
|
|
||
| Ниже таблица с результатами Perf тестов. | ||
|
|
||
| В таблице представлено: n - размер вектора, время выполнения SEQ и MPI версии для 4-х процессов (в милисекундах): | ||
|
|
||
| | Размер данных (n) | SEQ версия (ms)| MPI версия (ms) | Ускорение | | ||
| |-------------------|----------------|------------------|----------| | ||
| | 5 000 000 | 96 | 114 | 0,84 | | ||
| | 7 500 000 | 173,5 | 183 | 0,94 | | ||
| | 10 000 000 | 372 | 219 | 1,69 | | ||
|
|
||
| *результат был получен при запуске build/bin/ppc_perf_tests* | ||
|
|
||
| При замерах была получена данная таблица. | ||
| Мнjю не было получено ожидаемое ускорение в 8 раз. | ||
| Это нормально, так как чтобы появился рабочий процесс нужно выполнить команду операционной системы для его создания, что занимает много времени в масштабах задачи суммирования элементов вектора. | ||
| Операция суммирования отлично векторизуется и выполняется за 1 тик процессора на современных процессорах с архитектурой x86.Так же много времени забирает операция раздачи элементов вектора каждому процессу и рассчет смещений и размеров пераедаваемых пакетов. Поэтому ожидаемо что прирост скорости начнет проявлятся при действительно больших данных. | ||
|
|
||
| ## 7. Заключение | ||
| В результате проделанной работы были реализованы версии MPI, SEQ алгоритма нахождения суммы элементов вектора. | ||
| Было так же показано, что MPI версия работает быстрее SEQ при больших данных, а при небольших - наоборот. | ||
|
|
||
|
|
||
| ## Источники | ||
| 1. [cppreference.com](https://en.cppreference.com/) | ||
| 2. [стандарт с++](https://www.open-std.org) | ||
| 3. [Документация OpenMPI](https://www.open-mpi.org/doc/) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #pragma once | ||
|
|
||
| #include "kurpiakov_a_elem_vec_sum/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
| class KurpiakovAElemVecSumSEQ : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kSEQ; | ||
| } | ||
| explicit KurpiakovAElemVecSumSEQ(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #include "kurpiakov_a_elem_vec_sum/seq/include/ops_seq.hpp" | ||
|
|
||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "kurpiakov_a_elem_vec_sum/common/include/common.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
| KurpiakovAElemVecSumSEQ::KurpiakovAElemVecSumSEQ(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumSEQ::ValidationImpl() { | ||
| bool res = (GetOutput() == 0) && (std::cmp_equal((std::get<1>(GetInput()).size()), std::get<0>(GetInput()))); | ||
| return res; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumSEQ::PreProcessingImpl() { | ||
| GetOutput() = 0; | ||
| return true; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumSEQ::RunImpl() { | ||
| std::vector<int> vec = std::get<1>(GetInput()); | ||
| OutType res = 0LL; | ||
| for (const int &it : vec) { | ||
| res += static_cast<OutType>(it); | ||
| } | ||
| GetOutput() = res; | ||
| return true; | ||
| } | ||
|
|
||
| bool KurpiakovAElemVecSumSEQ::PostProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "tasks_type": "processes", | ||
| "tasks": { | ||
| "mpi": "enabled", | ||
| "seq": "enabled" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| #include <gtest/gtest.h> | ||
|
|
||
| #include <array> | ||
| #include <cmath> | ||
| #include <cstddef> | ||
| #include <cstdlib> | ||
| #include <string> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "kurpiakov_a_elem_vec_sum/common/include/common.hpp" | ||
| #include "kurpiakov_a_elem_vec_sum/mpi/include/ops_mpi.hpp" | ||
| #include "kurpiakov_a_elem_vec_sum/seq/include/ops_seq.hpp" | ||
| #include "util/include/func_test_util.hpp" | ||
| #include "util/include/util.hpp" | ||
|
|
||
| namespace kurpiakov_a_elem_vec_sum { | ||
| class KurpiakovAElemVecSumFuncTest : public ppc::util::BaseRunFuncTests<InType, OutType, TestType> { | ||
| public: | ||
| static std::string PrintTestParam(const TestType &test_param) { | ||
| return std::get<1>(test_param); | ||
| } | ||
|
|
||
| protected: | ||
| void SetUp() override { | ||
| TestType param = std::get<static_cast<std::size_t>(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); | ||
| input_data_ = std::get<0>(param); | ||
| expected_data_ = std::get<2>(param); | ||
| } | ||
|
|
||
| bool CheckTestOutputData(OutType &output_data) final { | ||
| return (output_data == expected_data_); | ||
| } | ||
|
|
||
| InType GetTestInputData() final { | ||
| return input_data_; | ||
| } | ||
|
|
||
| private: | ||
| InType input_data_{0, {}}; | ||
| OutType expected_data_{0}; | ||
| }; | ||
|
|
||
| namespace { | ||
| TEST_P(KurpiakovAElemVecSumFuncTest, ElemVecSum) { | ||
| ExecuteTest(GetParam()); | ||
| } | ||
|
|
||
| const std::array<TestType, 10> kTestParam = { | ||
| std::make_tuple(std::make_tuple(0, std::vector<int>{}), "test1_empty", 0LL), | ||
| std::make_tuple(std::make_tuple(1, std::vector<int>{5}), "test2_single", 5LL), | ||
| std::make_tuple(std::make_tuple(3, std::vector<int>{1, 2, 3}), "test3_positive", 6LL), | ||
| std::make_tuple(std::make_tuple(3, std::vector<int>{0, 0, 0}), "test4_zeros", 0LL), | ||
| std::make_tuple(std::make_tuple(3, std::vector<int>{1, -2, 3}), "test5_mixed", 2LL), | ||
| std::make_tuple(std::make_tuple(2, std::vector<int>{2147483646, 1}), "test6_border", 2147483647LL), | ||
| std::make_tuple(std::make_tuple(2, std::vector<int>{2147483646, 2147483647}), "test7_overflow", 4294967293LL), | ||
| std::make_tuple(std::make_tuple(3, std::vector<int>{-1, -2, -3}), "test8_negative", -6LL), | ||
| std::make_tuple(std::make_tuple(4, std::vector<int>{1, -1, 2, -2}), "test9_alternating", 0LL)}; | ||
|
|
||
| const auto kTestTasksList = | ||
| std::tuple_cat(ppc::util::AddFuncTask<kurpiakov_a_elem_vec_sum::KurpiakovAElemVecSumMPI, InType>( | ||
| kTestParam, PPC_SETTINGS_kurpiakov_a_elem_vec_sum), | ||
| ppc::util::AddFuncTask<kurpiakov_a_elem_vec_sum::KurpiakovAElemVecSumSEQ, InType>( | ||
| kTestParam, PPC_SETTINGS_kurpiakov_a_elem_vec_sum)); | ||
|
|
||
| const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); | ||
|
|
||
| const auto kPerfTestName = KurpiakovAElemVecSumFuncTest::PrintFuncTestName<KurpiakovAElemVecSumFuncTest>; | ||
|
|
||
| // NOLINTNEXTLINE | ||
| INSTANTIATE_TEST_SUITE_P(KurpiakovAVec, KurpiakovAElemVecSumFuncTest, kGtestValues, kPerfTestName); | ||
|
|
||
| } // namespace | ||
|
|
||
| } // namespace kurpiakov_a_elem_vec_sum |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.