-
Notifications
You must be signed in to change notification settings - Fork 80
Лузан Егор. Технология SEQ-MPI. Сумма значений по строкам матрицы. Вариант 11 #73
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 36 commits into
learning-process:master
from
smallAbyss:luzan_e_matrix_rows_sum
Dec 12, 2025
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
e07b139
add student folder
smallAbyss a3bbc5a
base task solution
smallAbyss 7d9173e
clang-format fix
smallAbyss 1751f66
pre-commit fix
smallAbyss a5371bb
yaml fix
smallAbyss 24be004
increase matrix sizes
smallAbyss ce8d488
change int to size_t for matrix sizes
smallAbyss b51ae83
change matrix sizes
smallAbyss c292d20
clang format fix
smallAbyss df0cfa2
reduce matrix sizes
smallAbyss 35c1fe3
clang-tidy fix
smallAbyss 1e48841
add func tests
smallAbyss 93bae7f
clang-format fix
smallAbyss a08851a
another clang-tidy fix
smallAbyss 6f4e8e1
another clang-format fix
smallAbyss 36a93a2
change perf tests data
smallAbyss afc425c
add report.md
smallAbyss 2932a7e
add func tests
smallAbyss 349ccb8
mpi fix
smallAbyss 87a1ba2
load h and w only for root & sizet fix
smallAbyss 48d5185
change report
smallAbyss f8c6979
fix grammatical mistakes
smallAbyss ac58228
clang-format fix
smallAbyss 6a3322a
clang-tidy fix
smallAbyss c54828c
add cstddef for sizet
smallAbyss 394fd88
clang-format fix
smallAbyss 5fed4ab
fix include
smallAbyss 8898854
codecov fix
smallAbyss 79b30b4
points
smallAbyss 55a1ab4
remove unused picture
smallAbyss 7f85672
fix checks
smallAbyss a0d559a
change mpi_reduce to mpi_gatherv
smallAbyss 708650c
change matrix sizes sharing
smallAbyss 187c7ac
some changes
smallAbyss 16dced1
clang-format fix
smallAbyss 56be159
report update
smallAbyss 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,15 @@ | ||
| #pragma once | ||
|
|
||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace luzan_e_matrix_rows_sum { | ||
|
|
||
| using InType = std::tuple<std::vector<int>, int, int>; // matrix, height, width | ||
| using OutType = std::vector<int>; // vec of sums, size = height | ||
| using TestType = std::tuple<int, int>; // height & width | ||
| using BaseTask = ppc::task::Task<InType, OutType>; | ||
|
|
||
| } // namespace luzan_e_matrix_rows_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,22 @@ | ||
| #pragma once | ||
|
|
||
| #include "luzan_e_matrix_rows_sum/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace luzan_e_matrix_rows_sum { | ||
|
|
||
| class LuzanEMatrixRowsSumMPI : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kMPI; | ||
| } | ||
| explicit LuzanEMatrixRowsSumMPI(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace luzan_e_matrix_rows_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,130 @@ | ||
| #include "luzan_e_matrix_rows_sum/mpi/include/ops_mpi.hpp" | ||
|
|
||
| #include <mpi.h> | ||
|
|
||
| #include <cstddef> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "luzan_e_matrix_rows_sum/common/include/common.hpp" | ||
|
|
||
| namespace luzan_e_matrix_rows_sum { | ||
|
|
||
| LuzanEMatrixRowsSumMPI::LuzanEMatrixRowsSumMPI(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetOutput() = {}; | ||
|
|
||
| // saving matrix only if it's rank=0 | ||
| int rank = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
|
|
||
| if (rank == 0) { | ||
| GetInput() = in; | ||
| } else { | ||
| GetInput() = {}; | ||
| } | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumMPI::ValidationImpl() { | ||
| int rank = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
| if (rank != 0) { | ||
| return true; | ||
| } | ||
|
|
||
| int height = std::get<1>(GetInput()); | ||
| int width = std::get<2>(GetInput()); | ||
| return std::get<0>(GetInput()).size() == static_cast<size_t>(height) * static_cast<size_t>(width) && height > 0 && | ||
| width > 0; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumMPI::PreProcessingImpl() { | ||
| int rank = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
| if (rank != 0) { | ||
| return true; | ||
| } | ||
|
allnes marked this conversation as resolved.
|
||
|
|
||
| int height = std::get<1>(GetInput()); | ||
| GetOutput().resize(height); | ||
| for (int row = 0; row < height; row++) { | ||
| GetOutput()[row] = 0; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumMPI::RunImpl() { | ||
| // mpi things | ||
| int height = 0; | ||
| int width = 0; | ||
| std::tuple_element_t<0, InType> mat; | ||
|
|
||
| int rank = 0; | ||
| int size = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &size); | ||
|
|
||
| // getting input matrix on rank=0 | ||
| // getting & sharing matrix sizes | ||
| std::vector<int> dim(2, 0); | ||
| if (rank == 0) { | ||
| mat = std::get<0>(GetInput()); | ||
| height = std::get<1>(GetInput()); | ||
| width = std::get<2>(GetInput()); | ||
| } | ||
| MPI_Bcast(&height, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
| MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| // calcilating shifts & rows_per_proc (only about rows rigth now) | ||
| int rest = height % size; | ||
| std::vector<int> shift(size, 0); | ||
| std::vector<int> per_proc(size, height / size); // rows per proc | ||
|
|
||
| int accumulator = 0; | ||
| for (int i = 0; i < size; i++) { | ||
| if (rest > 0) { | ||
| per_proc[i]++; | ||
| rest--; | ||
| } | ||
| shift[i] = accumulator; | ||
| accumulator = per_proc[i] + shift[i]; | ||
| } | ||
|
|
||
| // preparing to recieve data | ||
| std::vector<int> recv(static_cast<size_t>(per_proc[rank] * width)); | ||
|
|
||
| for (int i = 0; i < size; i++) { | ||
| per_proc[i] *= width; // now it's about elements | ||
| shift[i] *= width; | ||
| } | ||
| MPI_Scatterv(mat.data(), per_proc.data(), shift.data(), MPI_INT, recv.data(), per_proc[rank], MPI_INT, 0, | ||
| MPI_COMM_WORLD); | ||
| mat.clear(); // no need anymore | ||
|
|
||
| // calculating | ||
| std::vector<int> rows_sum(static_cast<size_t>(per_proc[rank] / width)); // sums | ||
| int rows_to_calc = static_cast<int>(per_proc[rank] / width); | ||
| for (int row = 0; row < rows_to_calc; row++) { | ||
| for (int col = 0; col < width; col++) { | ||
| rows_sum[row] += recv[(row * width) + col]; | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < size; i++) { | ||
| per_proc[i] /= width; // back to rows | ||
| shift[i] /= width; | ||
| } | ||
|
|
||
| std::vector<int> fin_sum(height); | ||
| MPI_Gatherv(rows_sum.data(), rows_to_calc, MPI_INT, fin_sum.data(), per_proc.data(), shift.data(), MPI_INT, 0, | ||
| MPI_COMM_WORLD); | ||
| MPI_Bcast(fin_sum.data(), height, MPI_INT, 0, MPI_COMM_WORLD); | ||
| GetOutput() = fin_sum; | ||
| return true; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumMPI::PostProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace luzan_e_matrix_rows_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,87 @@ | ||
| # <Сумма значений по строкам матрицы> | ||
|
|
||
| - Student: Лузан Егор Андреевич, group 3823Б1ФИ3 | ||
| - Technology: SEQ | MPI | ||
| - Variant: 11 | ||
|
|
||
| ## 1. Introduction | ||
| Цель работы — реализовать и сравнить две версии программы, вычисляющей сумму элементов в каждой строке матрицы: | ||
| 1. последовательную, | ||
| 2. параллельную, использующую библиотеку **MPI**. | ||
|
|
||
| Подобная задача встречается при обработке больших таблиц данных, изображений, численных расчётах. | ||
|
|
||
| Ожидается ускорение mpi версии относительно последовательной версии. | ||
|
|
||
| ## 2. Problem Statement | ||
| Дана матрица A размера `height × width`. | ||
| Требуется вычислить вектор $sum$ размера `width`, где: | ||
| $$sum[i] = \sum_{j=0}^{width-1} A_{i\_j}$$ | ||
|
|
||
| **Входные данные:** | ||
| - Матрица в форме вектора `(std::vector)` размера `height × width` состоящая из целых чисел. | ||
|
|
||
| **Выходные данные**: | ||
| - Вектор `(std::vector)` размера `height` состоящий из целых чисел, каждое из которых является суммой строки матрицы. | ||
|
|
||
| **Ограничения:** | ||
| - элементы матрицы — целые числа. | ||
| - элементы матрицы лежат в диапазоне -`[0; 42000]`. | ||
|
|
||
| ## 3. Baseline Algorithm (Sequential) | ||
| - Инициализация всех элементов выходного вектора нулями. | ||
| - Последовательный обход всех строк исходной матрицы, производя суммирование элементов в них и записывая результат в соответствующий элемент выходного вектора. | ||
|
|
||
| ## 4. Parallelization Scheme | ||
| **Распределение данных:** | ||
| - Для каждого процесса: | ||
| 1. Делим высоту матрицы нацело на количество процессов, получая `rows_per_proc` - минимальное количество строк для обработки каждый процессом. | ||
| 2. Получаем остаток `rest` от предыдущего деления. | ||
| 3. Раскладываем оставшиеся `rest` строк по процессам по одной, начиная с `rank=0`. Также вычисляем `shift` - массив смещений, который будет использован при рассылке данных с корневого процесса. | ||
| 4. Таким образом первые `rest` процессов обработают `rows_per_proc` + 1 строку, остальные `rows_per_proc`. | ||
|
|
||
| **Роли рангов:** | ||
| - Root-процесс получает матрицу и её размеры. | ||
| - Root-процесс рассылает остальным процессам части матрицы для вычислений. | ||
| - Во время вычисления сумм процессы всех рангов имеют одинаковые задачи. | ||
| - После вычисления итоговый результат будет записан в процессе `rank = 0` с помощью `MPI_Reduce()`. | ||
|
|
||
| ## 5. Implementation Details | ||
| - Для тестов производительности матрица генерируется внутри программы. Результат заранее предсказуем. | ||
| - Загрузка матрицы производиться только на root-процесс для экономии памяти. | ||
| - Работа программы проверена на матрицах на матрицах состоящих только из одного столбца/строки, на матрицы из одного элемента. | ||
|
|
||
| ## 6. Experimental Setup | ||
| - Hardware/OS: | ||
| - CPU: Intel Core i7-13620H; P-cores-6, E-cores-4. | ||
| - RAM: 16 GB RAM. | ||
| - OS: Windows 11, x64. | ||
| - Toolchain: | ||
| - Cmake 3.28.3. | ||
| - Компилятор: gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0. | ||
| - Использовался Docker-контейнер с Ubuntu 24.04.2 LTS. | ||
| - Режим сборки: Release. | ||
|
|
||
| - Data: Для замера производительности использовалась матрица размером 14 000 × 14 000, элементы которой представляют собой целые последовательные числа от 0 до 42 000. | ||
|
|
||
| ## 7. Results and Discussion | ||
|
|
||
| ### 7.1 Correctness | ||
| Корректность работы проверена с помощью GoogleTest на матрицах размерностями 3×3, 2×5, 10×70, 2000×5, 5×2000, 1×1. | ||
|
|
||
| ### 7.2 Performance | ||
|
|
||
| | Mode | Count | Time, s | Speedup | Efficiency | | ||
| | ---- | ----- | ------------------ | ------- | ---------- | | ||
| | seq | 1 | 0,06262 | 1.00 | N/A | | ||
| | mpi | 2 | 0,71973 | 0.08 | 4% | | ||
| | mpi | 4 | 0,60037 | 0.10 | 2% | | ||
|
|
||
| ## 8. Conclusions | ||
|
|
||
| Разработана программа, выполняющая поиск сумм строк матрицы. Также разработана её параллельная версия с использованием MPI. | ||
| Эффективность параллельного очень низкая из-за высоких затрат на пересылку данных и создание процессов. | ||
|
|
||
| ## 9. References | ||
| 1. Курс лекций ННГУ "Параллельное программирование для кластерных систем". | ||
| 2. Стандарт MPI. |
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,22 @@ | ||
| #pragma once | ||
|
|
||
| #include "luzan_e_matrix_rows_sum/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace luzan_e_matrix_rows_sum { | ||
|
|
||
| class LuzanEMatrixRowsSumSEQ : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kSEQ; | ||
| } | ||
| explicit LuzanEMatrixRowsSumSEQ(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; //= input data check | ||
| bool PreProcessingImpl() override; //= pre proc | ||
| bool RunImpl() override; //= PARALLEL | ||
| bool PostProcessingImpl() override; //= back to reality | ||
| }; | ||
|
|
||
| } // namespace luzan_e_matrix_rows_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,51 @@ | ||
| #include "luzan_e_matrix_rows_sum/seq/include/ops_seq.hpp" | ||
|
|
||
| #include <cstddef> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "luzan_e_matrix_rows_sum/common/include/common.hpp" | ||
|
|
||
| namespace luzan_e_matrix_rows_sum { | ||
|
|
||
| LuzanEMatrixRowsSumSEQ::LuzanEMatrixRowsSumSEQ(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = {}; | ||
| } | ||
|
|
||
|
allnes marked this conversation as resolved.
|
||
| bool LuzanEMatrixRowsSumSEQ::ValidationImpl() { | ||
|
allnes marked this conversation as resolved.
|
||
| int height = std::get<1>(GetInput()); | ||
| int width = std::get<2>(GetInput()); | ||
|
|
||
| return std::get<0>(GetInput()).size() == static_cast<size_t>(height) * static_cast<size_t>(width) && height > 0 && | ||
| width > 0; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumSEQ::PreProcessingImpl() { | ||
| int height = std::get<1>(GetInput()); | ||
| GetOutput().resize(height); | ||
| for (int row = 0; row < height; row++) { | ||
| GetOutput()[row] = 0; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumSEQ::RunImpl() { | ||
| int height = std::get<1>(GetInput()); | ||
| int width = std::get<2>(GetInput()); | ||
| const std::tuple_element_t<0, InType> &mat = std::get<0>(GetInput()); | ||
|
|
||
| for (int row = 0; row < height; row++) { | ||
| for (int col = 0; col < width; col++) { | ||
| GetOutput()[row] += mat[(width * row) + col]; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool LuzanEMatrixRowsSumSEQ::PostProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace luzan_e_matrix_rows_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,13 @@ | ||
| InheritParentConfig: true | ||
|
|
||
| Checks: > | ||
| -modernize-loop-convert, | ||
| -cppcoreguidelines-avoid-goto, | ||
| -cppcoreguidelines-avoid-non-const-global-variables, | ||
| -misc-use-anonymous-namespace, | ||
| -modernize-use-std-print, | ||
| -modernize-type-traits | ||
| CheckOptions: | ||
| - key: readability-function-cognitive-complexity.Threshold | ||
| value: 50 # Relaxed for tests |
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.