From 4634490e4dff4fb3378cc0e8aefbb9da3b360551 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Thu, 20 Nov 2025 01:30:26 +0300 Subject: [PATCH 01/21] Add test task --- .../common/include/common.hpp | 15 +++ .../data/pic.jpg | Bin 0 -> 23 bytes .../info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 22 +++++ .../mpi/src/ops_mpi.cpp | 72 +++++++++++++++ .../report.md | 0 .../seq/include/ops_seq.hpp | 22 +++++ .../seq/src/ops_seq.cpp | 60 ++++++++++++ .../settings.json | 7 ++ .../tests/.clang-tidy | 13 +++ .../tests/functional/main.cpp | 86 ++++++++++++++++++ .../tests/performance/main.cpp | 40 ++++++++ 12 files changed, 346 insertions(+) create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/info.json create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/report.md create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/settings.json create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp diff --git a/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp b/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp new file mode 100644 index 0000000000..af3e0933cf --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +using InType = int; +using OutType = int; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg b/tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..637624238c89d914613ed301968bffbf462bc110 GIT binary patch literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY + +#include +#include + +#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +GoriachevaKViolationOrderElemVecMPI::GoriachevaKViolationOrderElemVecMPI(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool GoriachevaKViolationOrderElemVecMPI::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool GoriachevaKViolationOrderElemVecMPI::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool GoriachevaKViolationOrderElemVecMPI::RunImpl() { + auto input = GetInput(); + if (input == 0) { + return false; + } + + for (InType i = 0; i < GetInput(); i++) { + for (InType j = 0; j < GetInput(); j++) { + for (InType k = 0; k < GetInput(); k++) { + std::vector tmp(i + j + k, 1); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); + GetOutput() -= i + j + k; + } + } + } + + const int num_threads = ppc::util::GetNumThreads(); + GetOutput() *= num_threads; + + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + GetOutput() /= num_threads; + } else { + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + + if (counter != 0) { + GetOutput() /= counter; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + return GetOutput() > 0; +} + +bool GoriachevaKViolationOrderElemVecMPI::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/report.md b/tasks/goriacheva_k_violation_order_elem_vec/report.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..50fca3c7fa --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +class GoriachevaKViolationOrderElemVecSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit GoriachevaKViolationOrderElemVecSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..f19c5ded57 --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp @@ -0,0 +1,60 @@ +#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" + +#include +#include + +#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +GoriachevaKViolationOrderElemVecSEQ::GoriachevaKViolationOrderElemVecSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool GoriachevaKViolationOrderElemVecSEQ::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool GoriachevaKViolationOrderElemVecSEQ::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool GoriachevaKViolationOrderElemVecSEQ::RunImpl() { + if (GetInput() == 0) { + return false; + } + + for (InType i = 0; i < GetInput(); i++) { + for (InType j = 0; j < GetInput(); j++) { + for (InType k = 0; k < GetInput(); k++) { + std::vector tmp(i + j + k, 1); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); + GetOutput() -= i + j + k; + } + } + } + + const int num_threads = ppc::util::GetNumThreads(); + GetOutput() *= num_threads; + + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + + if (counter != 0) { + GetOutput() /= counter; + } + return GetOutput() > 0; +} + +bool GoriachevaKViolationOrderElemVecSEQ::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/settings.json b/tasks/goriacheva_k_violation_order_elem_vec/settings.json new file mode 100644 index 0000000000..b1a0d52574 --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy b/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy new file mode 100644 index 0000000000..ef43b7aa8a --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy @@ -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 diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp new file mode 100644 index 0000000000..3b3e19e2b6 --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp @@ -0,0 +1,86 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" +#include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); + } + + protected: + void SetUp() override { + int width = -1; + int height = -1; + int channels = -1; + std::vector img; + // Read image in RGB to ensure consistent channel count + { + std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_violation_order_elem_vec, "pic.jpg"); + auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); + if (data == nullptr) { + throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + } + channels = STBI_rgb; + img = std::vector(data, data + (static_cast(width * height * channels))); + stbi_image_free(data); + if (std::cmp_not_equal(width, height)) { + throw std::runtime_error("width != height: "); + } + } + + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + } + + bool CheckTestOutputData(OutType &output_data) final { + return (input_data_ == output_data); + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_ = 0; +}; + +namespace { + +TEST_P(NesterovARunFuncTestsProcesses, MatmulFromPic) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_goriacheva_k_violation_order_elem_vec), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_goriacheva_k_violation_order_elem_vec)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = NesterovARunFuncTestsProcesses::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(PicMatrixTests, NesterovARunFuncTestsProcesses, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp new file mode 100644 index 0000000000..549baa25e9 --- /dev/null +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp @@ -0,0 +1,40 @@ +#include + +#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" +#include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace goriacheva_k_violation_order_elem_vec { + +class ExampleRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { + const int kCount_ = 100; + InType input_data_{}; + + void SetUp() override { + input_data_ = kCount_; + } + + bool CheckTestOutputData(OutType &output_data) final { + return input_data_ == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(ExampleRunPerfTestProcesses, RunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_goriacheva_k_violation_order_elem_vec); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = ExampleRunPerfTestProcesses::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, ExampleRunPerfTestProcesses, kGtestValues, kPerfTestName); + +} // namespace goriacheva_k_violation_order_elem_vec From 1ddbe9e1a152bc9823d8b2277b9f5bb4fc535881 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Mon, 29 Dec 2025 04:43:13 +0300 Subject: [PATCH 02/21] Add first task --- .../common/include/common.hpp | 5 +- .../data/pic.jpg | Bin 23 -> 0 bytes .../data/tests.json | 32 +++ .../mpi/include/ops_mpi.hpp | 4 + .../mpi/src/ops_mpi.cpp | 84 ++++---- .../report.md | 191 ++++++++++++++++++ .../seq/include/ops_seq.hpp | 5 + .../seq/src/ops_seq.cpp | 45 ++--- .../tests/functional/main.cpp | 109 +++++----- .../tests/performance/main.cpp | 55 +++-- 10 files changed, 401 insertions(+), 129 deletions(-) delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg create mode 100644 tasks/goriacheva_k_violation_order_elem_vec/data/tests.json diff --git a/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp b/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp index af3e0933cf..8cff19861f 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp @@ -2,14 +2,15 @@ #include #include +#include #include "task/include/task.hpp" namespace goriacheva_k_violation_order_elem_vec { -using InType = int; +using InType = std::vector; using OutType = int; -using TestType = std::tuple; +using TestType = std::tuple; using BaseTask = ppc::task::Task; } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg b/tasks/goriacheva_k_violation_order_elem_vec/data/pic.jpg deleted file mode 100644 index 637624238c89d914613ed301968bffbf462bc110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDYinput_vec; + int result = 0; }; } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp index 25d7d28298..5d888d8e92 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp @@ -2,7 +2,7 @@ #include -#include +//#include #include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" @@ -17,56 +17,72 @@ GoriachevaKViolationOrderElemVecMPI::GoriachevaKViolationOrderElemVecMPI(const I } bool GoriachevaKViolationOrderElemVecMPI::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + return true; } bool GoriachevaKViolationOrderElemVecMPI::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + input_vec = GetInput(); + result = 0; + return true; } bool GoriachevaKViolationOrderElemVecMPI::RunImpl() { - auto input = GetInput(); - if (input == 0) { - return false; - } - - for (InType i = 0; i < GetInput(); i++) { - for (InType j = 0; j < GetInput(); j++) { - for (InType k = 0; k < GetInput(); k++) { - std::vector tmp(i + j + k, 1); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); - GetOutput() -= i + j + k; - } + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int n = static_cast(input_vec.size()); + + MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); + + if (n <= 1) { + result = 0; + MPI_Bcast(&result, 1, MPI_INT, 0, MPI_COMM_WORLD); + return true; } - } - const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; + int base = n / size, rem = n % size; + int local_size = base + (rank < rem ? 1 : 0); + std::vector local(local_size); + + if (rank == 0) { + std::copy(input_vec.begin(), input_vec.begin() + local_size, local.begin()); + for (int r = 1; r < size; ++r) { + int sz = base + (r < rem ? 1 : 0); + if (sz){ + MPI_Send(input_vec.data() + r*base + std::min(r, rem), sz, MPI_INT, r, 0, MPI_COMM_WORLD); + } + } + } else if (local_size) { + MPI_Recv(local.data(), local_size, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + int local_count = 0; - if (rank == 0) { - GetOutput() /= num_threads; - } else { - int counter = 0; - for (int i = 0; i < num_threads; i++) { - counter++; + for (int i = 0; i + 1 < local_size; ++i){ + if (local[i] > local[i+1]){ + ++local_count; + } } - if (counter != 0) { - GetOutput() /= counter; + int left_last = 0, send_val = local_size ? local.back() : 0; + + MPI_Sendrecv(&send_val, 1, MPI_INT, rank+1 < size ? rank+1 : MPI_PROC_NULL, 1, + &left_last, 1, MPI_INT, rank > 0 ? rank-1 : MPI_PROC_NULL, 1, + MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + if (local_size && rank > 0 && left_last > local.front()){ + ++local_count; } - } - MPI_Barrier(MPI_COMM_WORLD); - return GetOutput() > 0; + MPI_Reduce(&local_count, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + MPI_Bcast(&result, 1, MPI_INT, 0, MPI_COMM_WORLD); + return true; } bool GoriachevaKViolationOrderElemVecMPI::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + GetOutput() = result; + return true; } } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/report.md b/tasks/goriacheva_k_violation_order_elem_vec/report.md index e69de29bb2..41a45a533a 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/report.md +++ b/tasks/goriacheva_k_violation_order_elem_vec/report.md @@ -0,0 +1,191 @@ +# Нахождение числа нарушений упорядоченности соседних элементов вектора +(последовательная и MPI-реализации) + +Студентка: Горячева Ксения Александровна, группа 3823Б1ФИ2 +Технологии: SEQ, MPI +Вариант: №6 + +--- + +## 1. Введение + +В работе рассматривается задача анализа упорядоченности одномерного массива целых чисел. + +Целью данной работы является разработка и исследование алгоритмов подсчёта количества нарушений порядка между соседними элементами вектора целых чисел, а также реализация параллельной версии алгоритма с использованием технологии MPI. + +Нарушением порядка считается ситуация, при которой для двух соседних элементов выполняется условие: + +a[i] > a[i+1] +--- + +## 2. Постановка задачи + +Входные данные: +вектор целых чисел v длины n. + +Выходные данные: +целое число — количество индексов i, для которых: + +0 ≤ i < n − 1 и v[i] > v[i+1] + +### Ограничения и допущения + +* элементы вектора могут принимать любые значения типа int; +* для векторов длины 0 или 1 результат равен 0; +* результаты SEQ и MPI реализаций должны совпадать. + +--- + +## 3. Последовательная реализация (SEQ) + +Последовательный алгоритм выполняет линейный проход по вектору и сравнивает каждую пару соседних элементов. + +Алгоритм: + +result = 0; +for(size_t i = 0; i + 1 < input_vec.size(); ++i){ + if (input_vec[i] > input_vec[i + 1]){ + ++result; + } +} + +Сложность алгоритма: + +* по времени: O(n) +* по памяти: O(1) (без учёта входных данных) + +--- + +## 4. Параллельная реализация (MPI) + +В MPI-версии входной вектор разбивается на непрерывные блоки элементов, которые распределяются между процессами. + +Каждый процесс подсчитывает количество нарушений порядка внутри своего блока, после чего дополнительно учитывается возможное нарушение на границе соседних блоков. + +### 4.1 Распределение данных + +Пусть: + +* n — размер вектора, +* p — количество MPI-процессов. + +Размер локального блока для процесса rank вычисляется как: + +base = n / p +rem = n % p +local_size = base + (rank < rem ? 1 : 0) + +Процесс с рангом 0 распределяет соответствующие части массива остальным процессам с помощью MPI_Send, а каждый процесс получает свой локальный подмассив. + +--- + +### 4.2 Локальный подсчёт + +Каждый процесс независимо подсчитывает количество нарушений порядка внутри своего блока: + +for (int i = 0; i + 1 < local_size; ++i){ + if (local[i] > local[i+1]){ + ++local_count; + } + } +--- + +### 4.3 Учёт границ блоков + +Так как пары элементов могут пересекать границу между блоками, необходимо дополнительно проверить соседние элементы между процессами. + +Для этого используется функция MPI_Sendrecv, позволяющая: + +* отправить последний элемент текущего блока следующему процессу; +* получить последний элемент предыдущего процесса. + +Если для процесса с rank > 0 выполняется: + +left_last > local.front() + +то счётчик локальных нарушений увеличивается на 1. + +--- + +### 4.4 Сбор результата + +После завершения локальных вычислений используется: + +* MPI_Reduce — для суммирования локальных результатов на процессе 0; +* MPI_Bcast — для рассылки итогового значения всем процессам. + +--- + +## 5. Тестирование корректности + +Для проверки корректности реализации был разработан набор функциональных тестов, включающий: + +* отсортированные и обратно отсортированные векторы; +* массивы с повторяющимися значениями; +* чередующиеся значения; +* отрицательные числа; +* массивы длины 0, 1 и 2; +* различные комбинации локальных спадов и подъёмов. + +Всего выполнено 58 функциональных тестов, все из которых успешно пройдены как для SEQ, так и для MPI версии. + +--- + +## 6. Экспериментальное исследование производительности + +Измерения проводились на векторе из 100 миллионов элементов с использованием 4 MPI-процессов. + +### Результаты измерений + +| Реализация | Процессы | Режим | Время (с) | +| ---------- | -------- | -------- | --------- | +| SEQ | 1 | task_run | 1.2996 | +| MPI | 4 | task_run | 0.3351 | + +### Расчёт ускорения и эффективности + +Ускорение: + +S = 1.2996 / 0.3351 ≈ 3.88 + +Эффективность: + +E = 3.88 / 4 ≈ 0.97 + +--- + +## 7. Анализ результатов + +Полученные результаты показывают, что при большом объёме входных данных параллельная реализация значительно превосходит последовательную по времени выполнения. + +Высокая эффективность объясняется следующими факторами: + +* линейная вычислительная сложность алгоритма; +* равномерное распределение данных между процессами; +* минимальный объём межпроцессного взаимодействия; +* использование MPI_Sendrecv, позволяющее корректно учитывать граничные элементы без сложных схем рассылки. + +В отличие от вариантов с перекрывающимся распределением данных, применённая схема демонстрирует хорошую масштабируемость. + +--- + +## 8. Заключение + +В ходе выполнения работы были реализованы и исследованы последовательная и параллельная версии алгоритма подсчёта нарушений порядка соседних элементов вектора. + +Основные результаты: + +* подтверждена корректность алгоритма на широком наборе тестов; +* реализована эффективная MPI-версия с учётом граничных условий; +* достигнуто ускорение порядка 3.9 раз на 4 процессах; +* показано, что для больших массивов MPI-реализация оправдана и эффективна. + +--- + +## 9. Используемые источники + +1. Pacheco P. — *An Introduction to Parallel Programming*. +2. Gropp W., Lusk E. — *Using MPI*. +3. Документация MPI Standard. + +--- diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp index 50fca3c7fa..9017268f8e 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp @@ -2,6 +2,7 @@ #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "task/include/task.hpp" +#include namespace goriacheva_k_violation_order_elem_vec { @@ -17,6 +18,10 @@ class GoriachevaKViolationOrderElemVecSEQ : public BaseTask { bool PreProcessingImpl() override; bool RunImpl() override; bool PostProcessingImpl() override; + + private: + std::vectorinput_vec; + int result = 0; }; } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp index f19c5ded57..a322b7ce85 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp @@ -1,6 +1,6 @@ #include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" -#include +//#include #include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" @@ -15,46 +15,35 @@ GoriachevaKViolationOrderElemVecSEQ::GoriachevaKViolationOrderElemVecSEQ(const I } bool GoriachevaKViolationOrderElemVecSEQ::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + return true; } bool GoriachevaKViolationOrderElemVecSEQ::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + input_vec = GetInput(); + result = 0; + return true; } bool GoriachevaKViolationOrderElemVecSEQ::RunImpl() { - if (GetInput() == 0) { - return false; - } - - for (InType i = 0; i < GetInput(); i++) { - for (InType j = 0; j < GetInput(); j++) { - for (InType k = 0; k < GetInput(); k++) { - std::vector tmp(i + j + k, 1); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); - GetOutput() -= i + j + k; - } - } - } - - const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; + input_vec = GetInput(); + result = 0; - int counter = 0; - for (int i = 0; i < num_threads; i++) { - counter++; + if (input_vec.size() <= 1) { + result = 0; } - if (counter != 0) { - GetOutput() /= counter; + for(size_t i = 0; i + 1 < input_vec.size(); ++i){ + if (input_vec[i] > input_vec[i + 1]){ + ++result; + } } - return GetOutput() > 0; + //GetOutput() = result; + return true; } bool GoriachevaKViolationOrderElemVecSEQ::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + GetOutput() = result; + return true; } } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp index 3b3e19e2b6..31f57082fa 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp @@ -1,16 +1,19 @@ #include -#include - -#include -#include -#include -#include -#include -#include +//#include + +//#include +//#include +//#include +//#include +//#include +//#include #include -#include -#include +//#include +//#include #include +#include +#include +//#include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" @@ -20,67 +23,71 @@ namespace goriacheva_k_violation_order_elem_vec { -class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests { + using FuncParam = ppc::util::FuncTestParam; + +class GoriachevaKViolationOrderElemVecFuncTests : public ppc::util::BaseRunFuncTests { public: - static std::string PrintTestParam(const TestType &test_param) { - return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); + static std::string PrintTestParam(const testing::TestParamInfo &info) { + return std::get(ppc::util::GTestParamIndex::kNameTest)>(info.param); } protected: void SetUp() override { - int width = -1; - int height = -1; - int channels = -1; - std::vector img; - // Read image in RGB to ensure consistent channel count - { - std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_violation_order_elem_vec, "pic.jpg"); - auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); - if (data == nullptr) { - throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); - } - channels = STBI_rgb; - img = std::vector(data, data + (static_cast(width * height * channels))); - stbi_image_free(data); - if (std::cmp_not_equal(width, height)) { - throw std::runtime_error("width != height: "); - } - } - - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + const auto ¶ms = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input = std::get<0>(params); + expected = std::get<1>(params); } - bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ == output_data); - } + InType GetTestInputData() final { return input; } - InType GetTestInputData() final { - return input_data_; + bool CheckTestOutputData(OutType &output_data) final { + return output_data == expected; } private: - InType input_data_ = 0; + InType input; + OutType expected{}; }; namespace { -TEST_P(NesterovARunFuncTestsProcesses, MatmulFromPic) { - ExecuteTest(GetParam()); -} +std::vector LoadTestParams() { + const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_violation_order_elem_vec, "tests.json"); + std::ifstream fin(path); + if (!fin.is_open()) throw std::runtime_error("Cannot open tests.json"); + + nlohmann::json j; + fin >> j; + + std::vector cases; + cases.reserve(j.size() * 2); -const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; + const std::string settings_path = PPC_SETTINGS_goriacheva_k_violation_order_elem_vec; + const std::string mpi_suffix = ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecMPI::GetStaticTypeOfTask(), settings_path); + const std::string seq_suffix = ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecSEQ::GetStaticTypeOfTask(), settings_path); -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_goriacheva_k_violation_order_elem_vec), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_goriacheva_k_violation_order_elem_vec)); + for (const auto &item : j) { + TestType tc{ item.at("input").get(), item.at("result").get(), item.at("name").get() }; -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + std::string mpi_name = std::get<2>(tc) + "_" + mpi_suffix; + cases.emplace_back(ppc::task::TaskGetter, mpi_name, tc); -const auto kPerfTestName = NesterovARunFuncTestsProcesses::PrintFuncTestName; + std::string seq_name = std::get<2>(tc) + "_" + seq_suffix; + cases.emplace_back(ppc::task::TaskGetter, seq_name, tc); + } + + return cases; +} + +const std::vector kFuncParams = LoadTestParams(); + +TEST_P(GoriachevaKViolationOrderElemVecFuncTests, VectorOrderViolations) { + ExecuteTest(GetParam()); +} -INSTANTIATE_TEST_SUITE_P(PicMatrixTests, NesterovARunFuncTestsProcesses, kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(FunctionalTests, GoriachevaKViolationOrderElemVecFuncTests, testing::ValuesIn(kFuncParams), + GoriachevaKViolationOrderElemVecFuncTests::PrintTestParam); } // namespace -} // namespace goriacheva_k_violation_order_elem_vec +} // namespace goriacheva_k_violation_order_elem_vec \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp index 549baa25e9..a0ace5b519 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp @@ -1,40 +1,67 @@ #include +#include +#include +#include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" #include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" +#include "util/include/util.hpp" namespace goriacheva_k_violation_order_elem_vec { -class ExampleRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const int kCount_ = 100; - InType input_data_{}; +class GoriachevaKViolationOrderElemVecPerfTests : public ppc::util::BaseRunPerfTests { + public: + static constexpr std::size_t kPerfSize = 100'000'000; + protected: void SetUp() override { - input_data_ = kCount_; - } + input.resize(kPerfSize); + + for (std::size_t i = 0; i < kPerfSize; ++i) { + if (i % 3 == 0) + input[i] = static_cast(kPerfSize - i); + else + input[i] = static_cast(i % 1000); + } - bool CheckTestOutputData(OutType &output_data) final { - return input_data_ == output_data; + expected = 1; } InType GetTestInputData() final { - return input_data_; + return input; + } + + bool CheckTestOutputData(OutType&) final { + return true; } + + private: + InType input; + OutType expected{}; }; -TEST_P(ExampleRunPerfTestProcesses, RunPerfModes) { +TEST_P(GoriachevaKViolationOrderElemVecPerfTests, RunPerfModes) { ExecuteTest(GetParam()); } -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_goriacheva_k_violation_order_elem_vec); +namespace { +auto BuildPerfParams() { + const auto all_tasks = + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_goriacheva_k_violation_order_elem_vec); + + return ppc::util::TupleToGTestValues(all_tasks); +} -const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); +const auto kPerfParams = BuildPerfParams(); -const auto kPerfTestName = ExampleRunPerfTestProcesses::CustomPerfTestName; +std::string MakePerfName(const ::testing::TestParamInfo& info) { + return GoriachevaKViolationOrderElemVecPerfTests::CustomPerfTestName(info); +} -INSTANTIATE_TEST_SUITE_P(RunModeTests, ExampleRunPerfTestProcesses, kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(PerfRunModes, GoriachevaKViolationOrderElemVecPerfTests, kPerfParams, MakePerfName); +} // namespace } // namespace goriacheva_k_violation_order_elem_vec From c047a87dff3a0f9e21425194fa79fba6b09e48fb Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Wed, 31 Dec 2025 05:41:48 +0300 Subject: [PATCH 03/21] Fix first task --- .../data/tests.json | 2 +- .../mpi/include/ops_mpi.hpp | 12 ++- .../mpi/src/ops_mpi.cpp | 96 ++++++++++--------- .../report.md | 42 ++++---- .../seq/include/ops_seq.hpp | 8 +- .../seq/src/ops_seq.cpp | 25 +++-- .../tests/functional/main.cpp | 53 +++++----- .../tests/performance/main.cpp | 31 +++--- 8 files changed, 143 insertions(+), 126 deletions(-) diff --git a/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json b/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json index c524cbc3e5..122f10838d 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json +++ b/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json @@ -29,4 +29,4 @@ { "name": "head_and_tail_inversions", "input": [9, 1, 2, 3, 4, 0], "result": 2 }, { "name": "interleaved_blocks", "input": [1, 1, 5, 5, 2, 2, 6, 6], "result": 1 }, { "name": "long_slope_with_glitch", "input": [0, 1, 2, 3, 4, 100, 5, 6, 7], "result": 1 } -] +] \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp index 660ced1175..e2bda73b9b 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "task/include/task.hpp" @@ -15,12 +17,16 @@ class GoriachevaKViolationOrderElemVecMPI : public BaseTask { private: bool ValidationImpl() override; bool PreProcessingImpl() override; + + std::vector GetLocalChunk(int rank, int size); + int CountLocalViolations(const std::vector &local) const; + int CheckBoundaryViolation(int rank, int size, const std::vector &local) const; + bool RunImpl() override; bool PostProcessingImpl() override; - private: - std::vectorinput_vec; - int result = 0; + std::vector input_vec_; + int result_ = 0; }; } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp index 5d888d8e92..35b81b7daf 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp @@ -2,11 +2,11 @@ #include -//#include +#include +#include #include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "util/include/util.hpp" namespace goriacheva_k_violation_order_elem_vec { @@ -21,68 +21,70 @@ bool GoriachevaKViolationOrderElemVecMPI::ValidationImpl() { } bool GoriachevaKViolationOrderElemVecMPI::PreProcessingImpl() { - input_vec = GetInput(); - result = 0; + input_vec_ = GetInput(); + result_ = 0; return true; } bool GoriachevaKViolationOrderElemVecMPI::RunImpl() { - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); - int n = static_cast(input_vec.size()); + int n = static_cast(input_vec_.size()); + MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); - - if (n <= 1) { - result = 0; - MPI_Bcast(&result, 1, MPI_INT, 0, MPI_COMM_WORLD); - return true; + if (n <= 1) { + result_ = 0; + MPI_Bcast(&result_, 1, MPI_INT, 0, MPI_COMM_WORLD); + return true; + } + + int base = n / size; + int rem = n % size; + int local_size = base + (rank < rem ? 1 : 0); + std::vector local(local_size); + + if (rank == 0) { + std::copy(input_vec_.begin(), input_vec_.begin() + local_size, local.begin()); + for (int rank_iter = 1; rank_iter < size; ++rank_iter) { + int sz = base + (rank_iter < rem ? 1 : 0); + if (sz != 0) { + MPI_Send(input_vec_.data() + static_cast((rank_iter * base) + std::min(rank_iter, rem)), sz, MPI_INT, + rank_iter, 0, MPI_COMM_WORLD); + } } + } else if (local_size > 0) { + MPI_Recv(local.data(), local_size, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } - int base = n / size, rem = n % size; - int local_size = base + (rank < rem ? 1 : 0); - std::vector local(local_size); - - if (rank == 0) { - std::copy(input_vec.begin(), input_vec.begin() + local_size, local.begin()); - for (int r = 1; r < size; ++r) { - int sz = base + (r < rem ? 1 : 0); - if (sz){ - MPI_Send(input_vec.data() + r*base + std::min(r, rem), sz, MPI_INT, r, 0, MPI_COMM_WORLD); - } - } - } else if (local_size) { - MPI_Recv(local.data(), local_size, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + int local_count = 0; + for (int i = 0; i + 1 < local_size; ++i) { + if (local[i] > local[i + 1]) { + ++local_count; } + } - int local_count = 0; + int send_val = (local_size > 0) ? local.back() : 0; + int left_last = 0; - for (int i = 0; i + 1 < local_size; ++i){ - if (local[i] > local[i+1]){ - ++local_count; - } - } + MPI_Sendrecv(&send_val, 1, MPI_INT, (rank + 1 < size) ? rank + 1 : MPI_PROC_NULL, 1, &left_last, 1, MPI_INT, + (rank > 0) ? rank - 1 : MPI_PROC_NULL, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - int left_last = 0, send_val = local_size ? local.back() : 0; + if (rank > 0 && local_size > 0 && left_last > local.front()) { + ++local_count; + } - MPI_Sendrecv(&send_val, 1, MPI_INT, rank+1 < size ? rank+1 : MPI_PROC_NULL, 1, - &left_last, 1, MPI_INT, rank > 0 ? rank-1 : MPI_PROC_NULL, 1, - MPI_COMM_WORLD, MPI_STATUS_IGNORE); - - if (local_size && rank > 0 && left_last > local.front()){ - ++local_count; - } + MPI_Reduce(&local_count, &result_, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + MPI_Bcast(&result_, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Reduce(&local_count, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); - MPI_Bcast(&result, 1, MPI_INT, 0, MPI_COMM_WORLD); - return true; + return true; } bool GoriachevaKViolationOrderElemVecMPI::PostProcessingImpl() { - GetOutput() = result; - return true; + GetOutput() = result_; + return true; } } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/report.md b/tasks/goriacheva_k_violation_order_elem_vec/report.md index 41a45a533a..7111318952 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/report.md +++ b/tasks/goriacheva_k_violation_order_elem_vec/report.md @@ -42,10 +42,10 @@ a[i] > a[i+1] Алгоритм: -result = 0; -for(size_t i = 0; i + 1 < input_vec.size(); ++i){ - if (input_vec[i] > input_vec[i + 1]){ - ++result; +result_ = 0; +for(size_t i = 0; i + 1 < input_vec_.size(); ++i){ + if (input_vec_[i] > input_vec_[i + 1]){ + ++result_; } } @@ -127,7 +127,7 @@ left_last > local.front() * массивы длины 0, 1 и 2; * различные комбинации локальных спадов и подъёмов. -Всего выполнено 58 функциональных тестов, все из которых успешно пройдены как для SEQ, так и для MPI версии. +Всего выполнено 60 функциональных тестов, все из которых успешно пройдены как для SEQ, так и для MPI версии. --- @@ -139,18 +139,27 @@ left_last > local.front() | Реализация | Процессы | Режим | Время (с) | | ---------- | -------- | -------- | --------- | -| SEQ | 1 | task_run | 1.2996 | -| MPI | 4 | task_run | 0.3351 | +| SEQ | 1 | task_run | 0.8988 | +| MPI | 2 | task_run | 0.3964 | +| MPI | 4 | task_run | 0.2755 | ### Расчёт ускорения и эффективности -Ускорение: +Ускорение на двух процессах: -S = 1.2996 / 0.3351 ≈ 3.88 +S = 0.8988 / 0.3964 ≈ 2.26 -Эффективность: +Эффективность на двух процессах: -E = 3.88 / 4 ≈ 0.97 +E = 2.26 / 4 ≈ 0.57 + +Ускорение на четырёх процессах: + +S = 0.8988 / 0.2755 ≈ 3.26 + +Эффективность на четырёх процессах: + +E = 3.26 / 4 ≈ 0.82 --- @@ -177,15 +186,16 @@ E = 3.88 / 4 ≈ 0.97 * подтверждена корректность алгоритма на широком наборе тестов; * реализована эффективная MPI-версия с учётом граничных условий; -* достигнуто ускорение порядка 3.9 раз на 4 процессах; +* достигнуто ускорение порядка 2.26 раз на 2 процессах; +* достигнуто ускорение порядка 3.26 раз на 4 процессах; * показано, что для больших массивов MPI-реализация оправдана и эффективна. --- ## 9. Используемые источники -1. Pacheco P. — *An Introduction to Parallel Programming*. -2. Gropp W., Lusk E. — *Using MPI*. -3. Документация MPI Standard. +1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) +2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) +3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) ---- +--- \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp index 9017268f8e..290a938a7b 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp @@ -1,8 +1,9 @@ #pragma once +#include + #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "task/include/task.hpp" -#include namespace goriacheva_k_violation_order_elem_vec { @@ -19,9 +20,8 @@ class GoriachevaKViolationOrderElemVecSEQ : public BaseTask { bool RunImpl() override; bool PostProcessingImpl() override; - private: - std::vectorinput_vec; - int result = 0; + std::vector input_vec_; + int result_ = 0; }; } // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp index a322b7ce85..0570f293f9 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp @@ -1,10 +1,9 @@ #include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" -//#include +#include #include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "util/include/util.hpp" namespace goriacheva_k_violation_order_elem_vec { @@ -19,30 +18,30 @@ bool GoriachevaKViolationOrderElemVecSEQ::ValidationImpl() { } bool GoriachevaKViolationOrderElemVecSEQ::PreProcessingImpl() { - input_vec = GetInput(); - result = 0; + input_vec_ = GetInput(); + result_ = 0; return true; } bool GoriachevaKViolationOrderElemVecSEQ::RunImpl() { - input_vec = GetInput(); - result = 0; + input_vec_ = GetInput(); + result_ = 0; - if (input_vec.size() <= 1) { - result = 0; + if (input_vec_.size() <= 1) { + result_ = 0; } - for(size_t i = 0; i + 1 < input_vec.size(); ++i){ - if (input_vec[i] > input_vec[i + 1]){ - ++result; + for (size_t i = 0; i + 1 < input_vec_.size(); ++i) { + if (input_vec_[i] > input_vec_[i + 1]) { + ++result_; } } - //GetOutput() = result; + return true; } bool GoriachevaKViolationOrderElemVecSEQ::PostProcessingImpl() { - GetOutput() = result; + GetOutput() = result_; return true; } diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp index 31f57082fa..408decada1 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp @@ -1,29 +1,22 @@ #include -//#include - -//#include -//#include -//#include -//#include -//#include -//#include + +#include +#include +#include +#include #include -//#include -//#include #include -#include -#include -//#include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" #include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" +#include "task/include/task.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" namespace goriacheva_k_violation_order_elem_vec { - using FuncParam = ppc::util::FuncTestParam; +using FuncParam = ppc::util::FuncTestParam; class GoriachevaKViolationOrderElemVecFuncTests : public ppc::util::BaseRunFuncTests { public: @@ -34,19 +27,21 @@ class GoriachevaKViolationOrderElemVecFuncTests : public ppc::util::BaseRunFuncT protected: void SetUp() override { const auto ¶ms = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input = std::get<0>(params); - expected = std::get<1>(params); + input_ = std::get<0>(params); + expected_ = std::get<1>(params); } - InType GetTestInputData() final { return input; } + InType GetTestInputData() final { + return input_; + } bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected; + return output_data == expected_; } private: - InType input; - OutType expected{}; + InType input_; + OutType expected_{}; }; namespace { @@ -54,7 +49,9 @@ namespace { std::vector LoadTestParams() { const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_violation_order_elem_vec, "tests.json"); std::ifstream fin(path); - if (!fin.is_open()) throw std::runtime_error("Cannot open tests.json"); + if (!fin.is_open()) { + throw std::runtime_error("Cannot open tests.json"); + } nlohmann::json j; fin >> j; @@ -63,11 +60,13 @@ std::vector LoadTestParams() { cases.reserve(j.size() * 2); const std::string settings_path = PPC_SETTINGS_goriacheva_k_violation_order_elem_vec; - const std::string mpi_suffix = ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecMPI::GetStaticTypeOfTask(), settings_path); - const std::string seq_suffix = ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecSEQ::GetStaticTypeOfTask(), settings_path); + const std::string mpi_suffix = + ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecMPI::GetStaticTypeOfTask(), settings_path); + const std::string seq_suffix = + ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecSEQ::GetStaticTypeOfTask(), settings_path); for (const auto &item : j) { - TestType tc{ item.at("input").get(), item.at("result").get(), item.at("name").get() }; + TestType tc{item.at("input").get(), item.at("result").get(), item.at("name").get()}; std::string mpi_name = std::get<2>(tc) + "_" + mpi_suffix; cases.emplace_back(ppc::task::TaskGetter, mpi_name, tc); @@ -85,9 +84,9 @@ TEST_P(GoriachevaKViolationOrderElemVecFuncTests, VectorOrderViolations) { ExecuteTest(GetParam()); } -INSTANTIATE_TEST_SUITE_P(FunctionalTests, GoriachevaKViolationOrderElemVecFuncTests, testing::ValuesIn(kFuncParams), - GoriachevaKViolationOrderElemVecFuncTests::PrintTestParam); +INSTANTIATE_TEST_SUITE_P(GoriachevaKViolationOrderElemVecFunctionalTests, GoriachevaKViolationOrderElemVecFuncTests, + testing::ValuesIn(kFuncParams), GoriachevaKViolationOrderElemVecFuncTests::PrintTestParam); } // namespace -} // namespace goriacheva_k_violation_order_elem_vec \ No newline at end of file +} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp index a0ace5b519..59c968ca35 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp @@ -1,13 +1,12 @@ #include + +#include #include -#include -#include #include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" #include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" #include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" -#include "util/include/util.hpp" namespace goriacheva_k_violation_order_elem_vec { @@ -17,29 +16,30 @@ class GoriachevaKViolationOrderElemVecPerfTests : public ppc::util::BaseRunPerfT protected: void SetUp() override { - input.resize(kPerfSize); + input_.resize(kPerfSize); for (std::size_t i = 0; i < kPerfSize; ++i) { - if (i % 3 == 0) - input[i] = static_cast(kPerfSize - i); - else - input[i] = static_cast(i % 1000); + if (i % 3 == 0) { + input_[i] = static_cast(kPerfSize - i); + } else { + input_[i] = static_cast(i % 1000); + } } - expected = 1; + expected_ = 1; } InType GetTestInputData() final { - return input; + return input_; } - bool CheckTestOutputData(OutType&) final { + bool CheckTestOutputData(OutType & /*output_data*/) final { return true; } private: - InType input; - OutType expected{}; + InType input_; + OutType expected_{}; }; TEST_P(GoriachevaKViolationOrderElemVecPerfTests, RunPerfModes) { @@ -57,11 +57,12 @@ auto BuildPerfParams() { const auto kPerfParams = BuildPerfParams(); -std::string MakePerfName(const ::testing::TestParamInfo& info) { +std::string MakePerfName(const ::testing::TestParamInfo &info) { return GoriachevaKViolationOrderElemVecPerfTests::CustomPerfTestName(info); } -INSTANTIATE_TEST_SUITE_P(PerfRunModes, GoriachevaKViolationOrderElemVecPerfTests, kPerfParams, MakePerfName); +INSTANTIATE_TEST_SUITE_P(GoriachevaKViolationOrderElemVecPerfomanceTests, GoriachevaKViolationOrderElemVecPerfTests, + kPerfParams, MakePerfName); } // namespace } // namespace goriacheva_k_violation_order_elem_vec From 6ef3a918a72268d86c76c9517684b871db72f595 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Wed, 31 Dec 2025 08:26:59 +0300 Subject: [PATCH 04/21] Fix2 first task --- .../common/include/common.hpp | 16 ++++ tasks/goriacheva_k_reduce/data/tests.json | 27 ++++++ tasks/goriacheva_k_reduce/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 26 ++++++ tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp | 92 +++++++++++++++++++ tasks/goriacheva_k_reduce/report.md | 0 .../seq/include/ops_seq.hpp | 22 +++++ tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp | 33 +++++++ tasks/goriacheva_k_reduce/settings.json | 7 ++ tasks/goriacheva_k_reduce/tests/.clang-tidy | 13 +++ .../tests/functional/main.cpp | 83 +++++++++++++++++ .../tests/performance/main.cpp | 31 +++++++ .../mpi/include/ops_mpi.hpp | 5 - 13 files changed, 359 insertions(+), 5 deletions(-) create mode 100644 tasks/goriacheva_k_reduce/common/include/common.hpp create mode 100644 tasks/goriacheva_k_reduce/data/tests.json create mode 100644 tasks/goriacheva_k_reduce/info.json create mode 100644 tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp create mode 100644 tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp create mode 100644 tasks/goriacheva_k_reduce/report.md create mode 100644 tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp create mode 100644 tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp create mode 100644 tasks/goriacheva_k_reduce/settings.json create mode 100644 tasks/goriacheva_k_reduce/tests/.clang-tidy create mode 100644 tasks/goriacheva_k_reduce/tests/functional/main.cpp create mode 100644 tasks/goriacheva_k_reduce/tests/performance/main.cpp diff --git a/tasks/goriacheva_k_reduce/common/include/common.hpp b/tasks/goriacheva_k_reduce/common/include/common.hpp new file mode 100644 index 0000000000..b43df70416 --- /dev/null +++ b/tasks/goriacheva_k_reduce/common/include/common.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +#include "task/include/task.hpp" + +namespace goriacheva_k_reduce { + +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/data/tests.json b/tasks/goriacheva_k_reduce/data/tests.json new file mode 100644 index 0000000000..4fbf71738c --- /dev/null +++ b/tasks/goriacheva_k_reduce/data/tests.json @@ -0,0 +1,27 @@ +[ + { + "name": "small", + "input": [1, 2, 3, 4], + "result": [10] + }, + { + "name": "single", + "input": [5], + "result": [5] + }, + { + "name": "negative", + "input": [10, -5, -5], + "result": [0] + }, + { + "name": "empty", + "input": [], + "result": [0] + }, + { + "name": "all_ones", + "input": [1, 1, 1, 1, 1], + "result": [5] + } +] \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/info.json b/tasks/goriacheva_k_reduce/info.json new file mode 100644 index 0000000000..062e9b0b85 --- /dev/null +++ b/tasks/goriacheva_k_reduce/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Ксения", + "last_name": "Горячева", + "middle_name": "Александровна", + "group_number": "3823Б1ФИ2", + "task_number": "2" + } +} diff --git a/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..686f1357ea --- /dev/null +++ b/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "goriacheva_k_reduce/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace goriacheva_k_reduce { + +class GoriachevaKReduceMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit GoriachevaKReduceMPI(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + std::vector local_input_; +}; + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..6021f46020 --- /dev/null +++ b/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp @@ -0,0 +1,92 @@ +#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" + +#include + +#include +#include + +#include "goriacheva_k_reduce/common/include/common.hpp" + +namespace goriacheva_k_reduce { + +GoriachevaKReduceMPI::GoriachevaKReduceMPI(const InType &in) { + InType tmp(in); + GetInput().swap(tmp); + SetTypeOfTask(GetStaticTypeOfTask()); +} + +bool GoriachevaKReduceMPI::ValidationImpl() { + return true; +} + +bool GoriachevaKReduceMPI::PreProcessingImpl() { + GetOutput().resize(1); + return true; +} + +bool GoriachevaKReduceMPI::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 = static_cast(GetInput().size()); + } + + MPI_Bcast(&total_size, 1, MPI_INT, 0, MPI_COMM_WORLD); + + if (total_size == 0) { + GetOutput()[0] = 0; + return true; + } + + int base = total_size / size; + int rem = total_size % size; + + int local_size = base + (rank < rem ? 1 : 0); + local_input_.resize(local_size); + + std::vector sendcounts; + std::vector displs; + + if (rank == 0) { + sendcounts.resize(size); + displs.resize(size); + int offset = 0; + for (int i = 0; i < size; ++i) { + sendcounts[i] = base + (i < rem ? 1 : 0); + displs[i] = offset; + offset += sendcounts[i]; + } + } + + MPI_Scatterv(rank == 0 ? GetInput().data() : nullptr, sendcounts.data(), displs.data(), MPI_INT, local_input_.data(), + local_size, MPI_INT, 0, MPI_COMM_WORLD); + + int local_sum = std::accumulate(local_input_.begin(), local_input_.end(), 0); + int global_sum = 0; + + if (rank == 0) { + global_sum = local_sum; + for (int i = 1; i < size; ++i) { + int tmp = 0; + MPI_Recv(&tmp, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + global_sum += tmp; + } + } else { + MPI_Send(&local_sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); + } + + MPI_Bcast(&global_sum, 1, MPI_INT, 0, MPI_COMM_WORLD); + GetOutput()[0] = global_sum; + + return true; +} + +bool GoriachevaKReduceMPI::PostProcessingImpl() { + return true; +} + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/report.md b/tasks/goriacheva_k_reduce/report.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp b/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..732e4393b2 --- /dev/null +++ b/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "goriacheva_k_reduce/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace goriacheva_k_reduce { + +class GoriachevaKReduceSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit GoriachevaKReduceSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp b/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..131b2fa4c3 --- /dev/null +++ b/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp @@ -0,0 +1,33 @@ +#include "goriacheva_k_reduce//seq/include/ops_seq.hpp" + +#include + +#include "goriacheva_k_reduce//common/include/common.hpp" + +namespace goriacheva_k_reduce { + +GoriachevaKReduceSEQ::GoriachevaKReduceSEQ(const InType &in) { + InType tmp(in); + GetInput().swap(tmp); + SetTypeOfTask(GetStaticTypeOfTask()); +} + +bool GoriachevaKReduceSEQ::ValidationImpl() { + return true; +} + +bool GoriachevaKReduceSEQ::PreProcessingImpl() { + GetOutput().resize(1); + return true; +} + +bool GoriachevaKReduceSEQ::RunImpl() { + GetOutput()[0] = std::accumulate(GetInput().begin(), GetInput().end(), 0); + return true; +} + +bool GoriachevaKReduceSEQ::PostProcessingImpl() { + return true; +} + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/settings.json b/tasks/goriacheva_k_reduce/settings.json new file mode 100644 index 0000000000..b1a0d52574 --- /dev/null +++ b/tasks/goriacheva_k_reduce/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/goriacheva_k_reduce/tests/.clang-tidy b/tasks/goriacheva_k_reduce/tests/.clang-tidy new file mode 100644 index 0000000000..ef43b7aa8a --- /dev/null +++ b/tasks/goriacheva_k_reduce/tests/.clang-tidy @@ -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 diff --git a/tasks/goriacheva_k_reduce/tests/functional/main.cpp b/tasks/goriacheva_k_reduce/tests/functional/main.cpp new file mode 100644 index 0000000000..46134c0e8e --- /dev/null +++ b/tasks/goriacheva_k_reduce/tests/functional/main.cpp @@ -0,0 +1,83 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "goriacheva_k_reduce/common/include/common.hpp" +#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_reduce/seq/include/ops_seq.hpp" +#include "task/include/task.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace goriacheva_k_reduce { + +using FuncParam = ppc::util::FuncTestParam; + +class GoriachevaKReduceFuncTests : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const testing::TestParamInfo &info) { + const auto &tc = std::get<2>(info.param); + const auto &name = std::get<2>(tc); + return name + "_" + std::to_string(info.index); + } + + protected: + void SetUp() override { + const auto ¶ms = std::get<2>(GetParam()); + input_ = std::get<0>(params); + expected_ = std::get<1>(params); + } + + bool CheckTestOutputData(OutType &output) final { + return output == expected_; + } + + InType GetTestInputData() final { + return input_; + } + + private: + InType input_; + OutType expected_; +}; + +static std::vector LoadTests() { + const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_reduce, "tests.json"); + + std::ifstream fin(path); + nlohmann::json j; + fin >> j; + + std::vector params; + + const std::string settings = PPC_SETTINGS_goriacheva_k_reduce; + const std::string mpi_suffix = ppc::task::GetStringTaskType(GoriachevaKReduceMPI::GetStaticTypeOfTask(), settings); + const std::string seq_suffix = ppc::task::GetStringTaskType(GoriachevaKReduceSEQ::GetStaticTypeOfTask(), settings); + + for (const auto &item : j) { + TestType tc{item.at("input").get(), item.at("result").get(), item.at("name").get()}; + + params.emplace_back(ppc::task::TaskGetter, std::get<2>(tc) + "_" + mpi_suffix, tc); + + params.emplace_back(ppc::task::TaskGetter, std::get<2>(tc) + "_" + seq_suffix, tc); + } + + return params; +} + +const auto kParams = LoadTests(); + +TEST_P(GoriachevaKReduceFuncTests, ReduceSum) { + ExecuteTest(GetParam()); +} + +INSTANTIATE_TEST_SUITE_P(GoriachevaKReduceFunctionalTests, GoriachevaKReduceFuncTests, testing::ValuesIn(kParams), + GoriachevaKReduceFuncTests::PrintTestParam); + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/tests/performance/main.cpp b/tasks/goriacheva_k_reduce/tests/performance/main.cpp new file mode 100644 index 0000000000..e14f259f8b --- /dev/null +++ b/tasks/goriacheva_k_reduce/tests/performance/main.cpp @@ -0,0 +1,31 @@ +#include + +#include "goriacheva_k_reduce/common/include/common.hpp" +#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_reduce/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace goriacheva_k_reduce { + +class GoriachevaKReducePerfTests : public ppc::util::BaseRunPerfTests { + protected: + InType GetTestInputData() final { + return {10'000'000, 1}; + } + + bool CheckTestOutputData(OutType &output) final { + return !output.empty(); + } +}; + +TEST_P(GoriachevaKReducePerfTests, RunPerfModes) { + ExecuteTest(GetParam()); +} + +INSTANTIATE_TEST_SUITE_P( + GoriachevaKReducePerfomanceTests, GoriachevaKReducePerfTests, + ppc::util::TupleToGTestValues(ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_goriacheva_k_reduce)), + GoriachevaKReducePerfTests::CustomPerfTestName); + +} // namespace goriacheva_k_reduce \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp index e2bda73b9b..336b9f58c1 100644 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp @@ -17,11 +17,6 @@ class GoriachevaKViolationOrderElemVecMPI : public BaseTask { private: bool ValidationImpl() override; bool PreProcessingImpl() override; - - std::vector GetLocalChunk(int rank, int size); - int CountLocalViolations(const std::vector &local) const; - int CheckBoundaryViolation(int rank, int size, const std::vector &local) const; - bool RunImpl() override; bool PostProcessingImpl() override; From ada4418e841f73f0e9ed0d8e8027bf9aa49e2220 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Wed, 31 Dec 2025 10:20:07 +0300 Subject: [PATCH 05/21] Add second task --- tasks/goriacheva_k_reduce/data/efficiency.png | Bin 0 -> 55559 bytes tasks/goriacheva_k_reduce/data/speedup.png | Bin 0 -> 54220 bytes .../data/time_vs_processes.png | Bin 0 -> 71631 bytes .../mpi/include/ops_mpi.hpp | 2 +- tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp | 2 +- tasks/goriacheva_k_reduce/report.md | 182 ++++++++++++++++++ .../seq/include/ops_seq.hpp | 2 +- tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp | 7 +- .../tests/functional/main.cpp | 5 +- .../tests/performance/main.cpp | 2 +- 10 files changed, 193 insertions(+), 9 deletions(-) create mode 100644 tasks/goriacheva_k_reduce/data/efficiency.png create mode 100644 tasks/goriacheva_k_reduce/data/speedup.png create mode 100644 tasks/goriacheva_k_reduce/data/time_vs_processes.png diff --git a/tasks/goriacheva_k_reduce/data/efficiency.png b/tasks/goriacheva_k_reduce/data/efficiency.png new file mode 100644 index 0000000000000000000000000000000000000000..46c6eb182553ddf8a5968db89736567b1eb24127 GIT binary patch literal 55559 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 z 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�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 G@c#iz1jHNw literal 0 HcmV?d00001 diff --git a/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp index 686f1357ea..76c6259ad0 100644 --- a/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp @@ -23,4 +23,4 @@ class GoriachevaKReduceMPI : public BaseTask { std::vector local_input_; }; -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp index 6021f46020..dd44d68ba8 100644 --- a/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp @@ -89,4 +89,4 @@ bool GoriachevaKReduceMPI::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/report.md b/tasks/goriacheva_k_reduce/report.md index e69de29bb2..f44de52d3e 100644 --- a/tasks/goriacheva_k_reduce/report.md +++ b/tasks/goriacheva_k_reduce/report.md @@ -0,0 +1,182 @@ +# Передача от всех одному (Reduce) +(последовательная и MPI-реализации) + +Студентка: Горячева Ксения Александровна, группа 3823Б1ФИ2 +Технологии: SEQ, MPI +Вариант: Reduce (Sum) + +--- + +## 1. Введение + +Операция Reduce является одной из базовых коллективных операций в параллельных вычислениях. Её назначение — собрать данные со всех параллельных процессов, применить к ним ассоциативную операцию (в данной работе — суммирование) и передать результат одному процессу (корневому). + +Целью данной работы является разработка и исследование операции Reduce для вычисления суммы элементов целочисленного вектора, а также анализ корректности и производительности реализованных алгоритмов. + +--- + +## 2. Постановка задачи + +Входные данные: +вектор целых чисел std::vector произвольной длины. + +Выходные данные: +вектор длины 1, содержащий сумму всех элементов входного массива. + +Для входного вектора v длины n требуется вычислить: +result = sum_{i=0}^{n-1} v[i] + +### Ограничения и допущения: + +* элементы вектора могут принимать любые значения типа int; +* для пустого вектора результат считается равным 0; +* MPI-реализация должна корректно работать при любом числе процессов. + +--- + +## 3. Базовый алгоритм (Последовательный) + +Последовательный алгоритм является тривиальным. Для нахождения суммы всех элементов вектора используется стандартная функция `std::accumulate` из заголовочного файла ``. Алгоритм итерируется по всем элементам входного вектора, последовательно прибавляя каждый элемент к внутреннему аккумулятору. Начальное значение аккумулятора равно нулю. + +Временная сложность такого алгоритма составляет O(N), где N — количество элементов в векторе. + +## 4. Параллельная реализация (MPI) + +Cемантика операции Reduce: все процессы участвуют в вычислении, итоговая сумма формируется на процессе с рангом 0 и затем рассылается всем процессам. + +### 4.1 Распределение данных + +Пусть: +n — размер входного вектора; +p — число MPI-процессов. + +Размер локального блока для процесса с рангом rank вычисляется следующим образом: +base = n / p rem = n % p local_size = base + (rank < rem ? 1 : 0) + +Процесс с рангом 0 формирует массивы sendcounts и displs, после чего используется коллективная операция: +MPI_Scatterv(...) + +Это позволяет корректно распределить данные даже при n % p ≠ 0. + +--- + +### 4.2 Локальные вычисления + +Каждый процесс вычисляет сумму элементов своего локального блока: +int local_sum = std::accumulate(local_input_.begin(), local_input_.end(), 0); + +--- + +### 4.3 Сбор глобального результата (Reduce) + +Сбор локальных сумм реализован вручную с использованием точечных операций: + +процессы с rank ≠ 0 отправляют свои local_sum на процесс 0 через MPI_Send; +процесс 0 принимает все значения с помощью MPI_Recv и аккумулирует итоговую сумму. + +if (rank == 0) { + global_sum = local_sum; + for (int i = 1; i < size; ++i) { + MPI_Recv(&tmp, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + global_sum += tmp; + } +} else { + MPI_Send(&local_sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); +} + +После этого итоговое значение рассылается всем процессам с помощью MPI_Bcast. + +--- + +## 5. Тестирование корректности + +Для проверки корректности разработан набор функциональных тестов, загружаемых из tests.json. + +Тесты включают: +* небольшой вектор; +* вектор из одного элемента; +* отрицательные значения; +* пустой вектор; +* вектор, заполненный единицами. + +Всего выполнено 10 функциональных тестов (по 5 тест-кейсов для SEQ и MPI реализаций). + +Все тесты успешно пройдены, что подтверждает корректность реализации. + +--- + +## 6. Экспериментальное исследование производительности + +Замеры производительности выполнялись с использованием performance-тестов фреймворка PPC. + +Параметры эксперимента: + +* входные данные: {10'000'000, 1} +* режимы измерений: +* pipeline +* task_run +* количество MPI-процессов: 2, 4, 8, 16, 32 + +### 6.1 Результаты измерений (task_run, MPI) + +Замеры производительности проводились для MPI-реализации на 1, 2, 3, 4, 8 и 16 процессах. За основу для расчетов (`task_run`) взято время выполнения на 1 процессе. + +| Число процессов (P) | Время (сек) | Ускорение (S) | Эффективность (E) | +|---------------------|-------------|---------------|----------------------| +| 1 | 0.00000400 | 1.00 | 1.00 | +| 2 | 0.00000762 | 0.52 | 0.26 | +| 4 | 0.00002508 | 0.16 | 0.04 | +| 8 | 0.00013296 | 0.03 | 0.004 | +| 16 | 0.00654368 | 0.0006 | 0.00004 | +| 32 | 0.01556248 | 0.0003 | 0.000008 | + +Графики производительности + +![График времени выполнения](data/time_vs_processes.png) +*Рис. 1. Зависимость времени выполнения от числа MPI-процессов.* + +![График ускорения](data/speedup.png) +*Рис. 2. Зависимость ускорения от числа MPI-процессов.* + +![График эффективности](data/efficiency.png) +*Рис. 3. Зависимость эффективности от числа MPI-процессов.* + +--- + +## 7. Анализ результатов + +Результаты показывают, что для данной задачи MPI-реализация не демонстрирует ускорения при увеличении числа процессов. + +Основные причины: +* операция суммирования является вычислительно очень простой; +* объём полезных вычислений на процесс резко уменьшается с ростом p; +* накладные расходы на: + MPI_Scatterv, + MPI_Send / MPI_Recv, + MPI_Bcast +начинают доминировать над временем локальных вычислений. + +С увеличением числа процессов время выполнения возрастает, что является наглядной иллюстрацией закона Амдала. + +--- + +## 8. Заключение + +В ходе выполнения работы были реализованы и исследованы последовательная и параллельная версии операции Reduce для вычисления суммы элементов вектора. + +Основные выводы: +* обе реализации корректны и успешно проходят функциональные тесты; +* MPI-версия корректно обрабатывает любые размеры входных данных; +* рост числа процессов приводит к увеличению времени выполнения из-за коммуникационных накладных расходов. + +--- + +## 9. Используемые источники + +1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) +2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) +3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) +4. std::accumulate documentation - [https://en.cppreference.com/w/cpp/algorithm/accumulate](https://en.cppreference.com/w/cpp/algorithm/accumulate) +5. MPI_Reduce documentation - [https://www.open-mpi.org/doc/v4.1/man3/MPI_Reduce.3.php](https://www.open-mpi.org/doc/v4.1/man3/MPI_Reduce.3.php) + +--- \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp b/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp index 732e4393b2..e8cf84e8ad 100644 --- a/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp @@ -19,4 +19,4 @@ class GoriachevaKReduceSEQ : public BaseTask { bool PostProcessingImpl() override; }; -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp b/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp index 131b2fa4c3..5576667fc7 100644 --- a/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp @@ -22,6 +22,11 @@ bool GoriachevaKReduceSEQ::PreProcessingImpl() { } bool GoriachevaKReduceSEQ::RunImpl() { + const auto input = GetInput(); + if (input.empty()) { + GetOutput()[0] = 0; + return true; + } GetOutput()[0] = std::accumulate(GetInput().begin(), GetInput().end(), 0); return true; } @@ -30,4 +35,4 @@ bool GoriachevaKReduceSEQ::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/tests/functional/main.cpp b/tasks/goriacheva_k_reduce/tests/functional/main.cpp index 46134c0e8e..187297a12e 100644 --- a/tasks/goriacheva_k_reduce/tests/functional/main.cpp +++ b/tasks/goriacheva_k_reduce/tests/functional/main.cpp @@ -2,10 +2,7 @@ #include #include -#include #include -#include -#include #include #include "goriacheva_k_reduce/common/include/common.hpp" @@ -80,4 +77,4 @@ TEST_P(GoriachevaKReduceFuncTests, ReduceSum) { INSTANTIATE_TEST_SUITE_P(GoriachevaKReduceFunctionalTests, GoriachevaKReduceFuncTests, testing::ValuesIn(kParams), GoriachevaKReduceFuncTests::PrintTestParam); -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/tests/performance/main.cpp b/tasks/goriacheva_k_reduce/tests/performance/main.cpp index e14f259f8b..cf9c25265a 100644 --- a/tasks/goriacheva_k_reduce/tests/performance/main.cpp +++ b/tasks/goriacheva_k_reduce/tests/performance/main.cpp @@ -28,4 +28,4 @@ INSTANTIATE_TEST_SUITE_P( PPC_SETTINGS_goriacheva_k_reduce)), GoriachevaKReducePerfTests::CustomPerfTestName); -} // namespace goriacheva_k_reduce \ No newline at end of file +} // namespace goriacheva_k_reduce From 27fc60971e00e632a03ab03073274699bb7c7ad9 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Wed, 31 Dec 2025 11:01:45 +0300 Subject: [PATCH 06/21] Fix second task --- .../common/include/common.hpp | 16 -- .../data/tests.json | 32 --- .../info.json | 9 - .../mpi/include/ops_mpi.hpp | 27 --- .../mpi/src/ops_mpi.cpp | 90 -------- .../report.md | 201 ------------------ .../seq/include/ops_seq.hpp | 27 --- .../seq/src/ops_seq.cpp | 48 ----- .../settings.json | 7 - .../tests/.clang-tidy | 13 -- .../tests/functional/main.cpp | 92 -------- .../tests/performance/main.cpp | 68 ------ 12 files changed, 630 deletions(-) delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/data/tests.json delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/info.json delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/report.md delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/settings.json delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp delete mode 100644 tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp diff --git a/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp b/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp deleted file mode 100644 index 8cff19861f..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/common/include/common.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "task/include/task.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -using InType = std::vector; -using OutType = int; -using TestType = std::tuple; -using BaseTask = ppc::task::Task; - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json b/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json deleted file mode 100644 index 122f10838d..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/data/tests.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { "name": "sorted_small", "input": [1, 2, 3, 4, 5, 6], "result": 0 }, - { "name": "reversed_small", "input": [6, 5, 4, 3, 2, 1], "result": 5 }, - { "name": "mixed_short", "input": [5, 1, 4, 2, 8], "result": 2 }, - { "name": "empty", "input": [], "result": 0 }, - { "name": "single", "input": [42], "result": 0 }, - { "name": "plateau", "input": [2, 2, 2, 2, 2], "result": 0 }, - { "name": "alternating", "input": [1, 3, 2, 4, 3, 5], "result": 2 }, - { "name": "two_blocks", "input": [4, 4, 4, 1, 1, 1], "result": 1 }, - { "name": "long_random_1", "input": [3, 8, 6, 6, 7, 2, 4, 5], "result": 2 }, - { "name": "long_random_2", "input": [7, 1, 5, 3, 9, 0, 2, 6], "result": 3 }, - { "name": "one_inversion_tail", "input": [1, 2, 3, 4, 0], "result": 1 }, - { "name": "one_inversion_head", "input": [9, 0, 1, 2, 3, 4], "result": 1 }, - { "name": "duplicates_and_drop", "input": [5, 5, 5, 3, 3, 3], "result": 1 }, - { "name": "zigzag", "input": [5, 1, 4, 2, 3], "result": 2 }, - { "name": "negatives", "input": [-1, 0, -2, 3, -5], "result": 2 }, - { "name": "two_element", "input": [2, 1], "result": 1 }, - { "name": "almost_sorted_end", "input": [1, 2, 3, 5, 4], "result": 1 }, - { "name": "periodic", "input": [1, 4, 1, 4, 1, 4, 1], "result": 3 }, - { "name": "random_middle_drop", "input": [10, 11, 12, 3, 13, 14], "result": 1 }, - { "name": "deep_valley", "input": [9, 8, 1, 2, 3, 4, 5, 6], "result": 2 }, - { "name": "wide_peak", "input": [1, 10, 9, 8, 7, 20], "result": 3 }, - { "name": "alternating_negative_positive", "input": [-3, 5, -2, 4, -1, 3], "result": 2 }, - { "name": "sorted_with_tail_dup", "input": [1, 2, 3, 4, 4], "result": 0 }, - { "name": "mountain_shape", "input": [1, 3, 5, 7, 6, 4, 2], "result": 3 }, - { "name": "wave_small", "input": [2, 1, 3, 2, 4, 3], "result": 3 }, - { "name": "large_plateau_drop", "input": [5, 5, 5, 5, 1], "result": 1 }, - { "name": "random_sparse", "input": [8, 3, 15, 7, 9, 2], "result": 3 }, - { "name": "head_and_tail_inversions", "input": [9, 1, 2, 3, 4, 0], "result": 2 }, - { "name": "interleaved_blocks", "input": [1, 1, 5, 5, 2, 2, 6, 6], "result": 1 }, - { "name": "long_slope_with_glitch", "input": [0, 1, 2, 3, 4, 100, 5, 6, 7], "result": 1 } -] \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/info.json b/tasks/goriacheva_k_violation_order_elem_vec/info.json deleted file mode 100644 index 78767be769..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/info.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "student": { - "first_name": "Ксения", - "last_name": "Горячева", - "middle_name": "Александровна", - "group_number": "3823Б1ФИ2", - "task_number": "1" - } -} diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp deleted file mode 100644 index 336b9f58c1..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "task/include/task.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -class GoriachevaKViolationOrderElemVecMPI : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kMPI; - } - explicit GoriachevaKViolationOrderElemVecMPI(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::vector input_vec_; - int result_ = 0; -}; - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp deleted file mode 100644 index 35b81b7daf..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/mpi/src/ops_mpi.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" - -#include - -#include -#include -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -GoriachevaKViolationOrderElemVecMPI::GoriachevaKViolationOrderElemVecMPI(const InType &in) { - SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = 0; -} - -bool GoriachevaKViolationOrderElemVecMPI::ValidationImpl() { - return true; -} - -bool GoriachevaKViolationOrderElemVecMPI::PreProcessingImpl() { - input_vec_ = GetInput(); - result_ = 0; - return true; -} - -bool GoriachevaKViolationOrderElemVecMPI::RunImpl() { - int rank = 0; - int size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - int n = static_cast(input_vec_.size()); - MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); - - if (n <= 1) { - result_ = 0; - MPI_Bcast(&result_, 1, MPI_INT, 0, MPI_COMM_WORLD); - return true; - } - - int base = n / size; - int rem = n % size; - int local_size = base + (rank < rem ? 1 : 0); - std::vector local(local_size); - - if (rank == 0) { - std::copy(input_vec_.begin(), input_vec_.begin() + local_size, local.begin()); - for (int rank_iter = 1; rank_iter < size; ++rank_iter) { - int sz = base + (rank_iter < rem ? 1 : 0); - if (sz != 0) { - MPI_Send(input_vec_.data() + static_cast((rank_iter * base) + std::min(rank_iter, rem)), sz, MPI_INT, - rank_iter, 0, MPI_COMM_WORLD); - } - } - } else if (local_size > 0) { - MPI_Recv(local.data(), local_size, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - } - - int local_count = 0; - for (int i = 0; i + 1 < local_size; ++i) { - if (local[i] > local[i + 1]) { - ++local_count; - } - } - - int send_val = (local_size > 0) ? local.back() : 0; - int left_last = 0; - - MPI_Sendrecv(&send_val, 1, MPI_INT, (rank + 1 < size) ? rank + 1 : MPI_PROC_NULL, 1, &left_last, 1, MPI_INT, - (rank > 0) ? rank - 1 : MPI_PROC_NULL, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - - if (rank > 0 && local_size > 0 && left_last > local.front()) { - ++local_count; - } - - MPI_Reduce(&local_count, &result_, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); - MPI_Bcast(&result_, 1, MPI_INT, 0, MPI_COMM_WORLD); - - return true; -} - -bool GoriachevaKViolationOrderElemVecMPI::PostProcessingImpl() { - GetOutput() = result_; - return true; -} - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/report.md b/tasks/goriacheva_k_violation_order_elem_vec/report.md deleted file mode 100644 index 7111318952..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/report.md +++ /dev/null @@ -1,201 +0,0 @@ -# Нахождение числа нарушений упорядоченности соседних элементов вектора -(последовательная и MPI-реализации) - -Студентка: Горячева Ксения Александровна, группа 3823Б1ФИ2 -Технологии: SEQ, MPI -Вариант: №6 - ---- - -## 1. Введение - -В работе рассматривается задача анализа упорядоченности одномерного массива целых чисел. - -Целью данной работы является разработка и исследование алгоритмов подсчёта количества нарушений порядка между соседними элементами вектора целых чисел, а также реализация параллельной версии алгоритма с использованием технологии MPI. - -Нарушением порядка считается ситуация, при которой для двух соседних элементов выполняется условие: - -a[i] > a[i+1] ---- - -## 2. Постановка задачи - -Входные данные: -вектор целых чисел v длины n. - -Выходные данные: -целое число — количество индексов i, для которых: - -0 ≤ i < n − 1 и v[i] > v[i+1] - -### Ограничения и допущения - -* элементы вектора могут принимать любые значения типа int; -* для векторов длины 0 или 1 результат равен 0; -* результаты SEQ и MPI реализаций должны совпадать. - ---- - -## 3. Последовательная реализация (SEQ) - -Последовательный алгоритм выполняет линейный проход по вектору и сравнивает каждую пару соседних элементов. - -Алгоритм: - -result_ = 0; -for(size_t i = 0; i + 1 < input_vec_.size(); ++i){ - if (input_vec_[i] > input_vec_[i + 1]){ - ++result_; - } -} - -Сложность алгоритма: - -* по времени: O(n) -* по памяти: O(1) (без учёта входных данных) - ---- - -## 4. Параллельная реализация (MPI) - -В MPI-версии входной вектор разбивается на непрерывные блоки элементов, которые распределяются между процессами. - -Каждый процесс подсчитывает количество нарушений порядка внутри своего блока, после чего дополнительно учитывается возможное нарушение на границе соседних блоков. - -### 4.1 Распределение данных - -Пусть: - -* n — размер вектора, -* p — количество MPI-процессов. - -Размер локального блока для процесса rank вычисляется как: - -base = n / p -rem = n % p -local_size = base + (rank < rem ? 1 : 0) - -Процесс с рангом 0 распределяет соответствующие части массива остальным процессам с помощью MPI_Send, а каждый процесс получает свой локальный подмассив. - ---- - -### 4.2 Локальный подсчёт - -Каждый процесс независимо подсчитывает количество нарушений порядка внутри своего блока: - -for (int i = 0; i + 1 < local_size; ++i){ - if (local[i] > local[i+1]){ - ++local_count; - } - } ---- - -### 4.3 Учёт границ блоков - -Так как пары элементов могут пересекать границу между блоками, необходимо дополнительно проверить соседние элементы между процессами. - -Для этого используется функция MPI_Sendrecv, позволяющая: - -* отправить последний элемент текущего блока следующему процессу; -* получить последний элемент предыдущего процесса. - -Если для процесса с rank > 0 выполняется: - -left_last > local.front() - -то счётчик локальных нарушений увеличивается на 1. - ---- - -### 4.4 Сбор результата - -После завершения локальных вычислений используется: - -* MPI_Reduce — для суммирования локальных результатов на процессе 0; -* MPI_Bcast — для рассылки итогового значения всем процессам. - ---- - -## 5. Тестирование корректности - -Для проверки корректности реализации был разработан набор функциональных тестов, включающий: - -* отсортированные и обратно отсортированные векторы; -* массивы с повторяющимися значениями; -* чередующиеся значения; -* отрицательные числа; -* массивы длины 0, 1 и 2; -* различные комбинации локальных спадов и подъёмов. - -Всего выполнено 60 функциональных тестов, все из которых успешно пройдены как для SEQ, так и для MPI версии. - ---- - -## 6. Экспериментальное исследование производительности - -Измерения проводились на векторе из 100 миллионов элементов с использованием 4 MPI-процессов. - -### Результаты измерений - -| Реализация | Процессы | Режим | Время (с) | -| ---------- | -------- | -------- | --------- | -| SEQ | 1 | task_run | 0.8988 | -| MPI | 2 | task_run | 0.3964 | -| MPI | 4 | task_run | 0.2755 | - -### Расчёт ускорения и эффективности - -Ускорение на двух процессах: - -S = 0.8988 / 0.3964 ≈ 2.26 - -Эффективность на двух процессах: - -E = 2.26 / 4 ≈ 0.57 - -Ускорение на четырёх процессах: - -S = 0.8988 / 0.2755 ≈ 3.26 - -Эффективность на четырёх процессах: - -E = 3.26 / 4 ≈ 0.82 - ---- - -## 7. Анализ результатов - -Полученные результаты показывают, что при большом объёме входных данных параллельная реализация значительно превосходит последовательную по времени выполнения. - -Высокая эффективность объясняется следующими факторами: - -* линейная вычислительная сложность алгоритма; -* равномерное распределение данных между процессами; -* минимальный объём межпроцессного взаимодействия; -* использование MPI_Sendrecv, позволяющее корректно учитывать граничные элементы без сложных схем рассылки. - -В отличие от вариантов с перекрывающимся распределением данных, применённая схема демонстрирует хорошую масштабируемость. - ---- - -## 8. Заключение - -В ходе выполнения работы были реализованы и исследованы последовательная и параллельная версии алгоритма подсчёта нарушений порядка соседних элементов вектора. - -Основные результаты: - -* подтверждена корректность алгоритма на широком наборе тестов; -* реализована эффективная MPI-версия с учётом граничных условий; -* достигнуто ускорение порядка 2.26 раз на 2 процессах; -* достигнуто ускорение порядка 3.26 раз на 4 процессах; -* показано, что для больших массивов MPI-реализация оправдана и эффективна. - ---- - -## 9. Используемые источники - -1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) -2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) -3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) - ---- \ No newline at end of file diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp deleted file mode 100644 index 290a938a7b..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "task/include/task.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -class GoriachevaKViolationOrderElemVecSEQ : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; - } - explicit GoriachevaKViolationOrderElemVecSEQ(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::vector input_vec_; - int result_ = 0; -}; - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp b/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp deleted file mode 100644 index 0570f293f9..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/seq/src/ops_seq.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" - -#include -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -GoriachevaKViolationOrderElemVecSEQ::GoriachevaKViolationOrderElemVecSEQ(const InType &in) { - SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = 0; -} - -bool GoriachevaKViolationOrderElemVecSEQ::ValidationImpl() { - return true; -} - -bool GoriachevaKViolationOrderElemVecSEQ::PreProcessingImpl() { - input_vec_ = GetInput(); - result_ = 0; - return true; -} - -bool GoriachevaKViolationOrderElemVecSEQ::RunImpl() { - input_vec_ = GetInput(); - result_ = 0; - - if (input_vec_.size() <= 1) { - result_ = 0; - } - - for (size_t i = 0; i + 1 < input_vec_.size(); ++i) { - if (input_vec_[i] > input_vec_[i + 1]) { - ++result_; - } - } - - return true; -} - -bool GoriachevaKViolationOrderElemVecSEQ::PostProcessingImpl() { - GetOutput() = result_; - return true; -} - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/settings.json b/tasks/goriacheva_k_violation_order_elem_vec/settings.json deleted file mode 100644 index b1a0d52574..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tasks_type": "processes", - "tasks": { - "mpi": "enabled", - "seq": "enabled" - } -} diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy b/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy deleted file mode 100644 index ef43b7aa8a..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/.clang-tidy +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp deleted file mode 100644 index 408decada1..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/functional/main.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" -#include "task/include/task.hpp" -#include "util/include/func_test_util.hpp" -#include "util/include/util.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -using FuncParam = ppc::util::FuncTestParam; - -class GoriachevaKViolationOrderElemVecFuncTests : public ppc::util::BaseRunFuncTests { - public: - static std::string PrintTestParam(const testing::TestParamInfo &info) { - return std::get(ppc::util::GTestParamIndex::kNameTest)>(info.param); - } - - protected: - void SetUp() override { - const auto ¶ms = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_ = std::get<0>(params); - expected_ = std::get<1>(params); - } - - InType GetTestInputData() final { - return input_; - } - - bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected_; - } - - private: - InType input_; - OutType expected_{}; -}; - -namespace { - -std::vector LoadTestParams() { - const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_violation_order_elem_vec, "tests.json"); - std::ifstream fin(path); - if (!fin.is_open()) { - throw std::runtime_error("Cannot open tests.json"); - } - - nlohmann::json j; - fin >> j; - - std::vector cases; - cases.reserve(j.size() * 2); - - const std::string settings_path = PPC_SETTINGS_goriacheva_k_violation_order_elem_vec; - const std::string mpi_suffix = - ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecMPI::GetStaticTypeOfTask(), settings_path); - const std::string seq_suffix = - ppc::task::GetStringTaskType(GoriachevaKViolationOrderElemVecSEQ::GetStaticTypeOfTask(), settings_path); - - for (const auto &item : j) { - TestType tc{item.at("input").get(), item.at("result").get(), item.at("name").get()}; - - std::string mpi_name = std::get<2>(tc) + "_" + mpi_suffix; - cases.emplace_back(ppc::task::TaskGetter, mpi_name, tc); - - std::string seq_name = std::get<2>(tc) + "_" + seq_suffix; - cases.emplace_back(ppc::task::TaskGetter, seq_name, tc); - } - - return cases; -} - -const std::vector kFuncParams = LoadTestParams(); - -TEST_P(GoriachevaKViolationOrderElemVecFuncTests, VectorOrderViolations) { - ExecuteTest(GetParam()); -} - -INSTANTIATE_TEST_SUITE_P(GoriachevaKViolationOrderElemVecFunctionalTests, GoriachevaKViolationOrderElemVecFuncTests, - testing::ValuesIn(kFuncParams), GoriachevaKViolationOrderElemVecFuncTests::PrintTestParam); - -} // namespace - -} // namespace goriacheva_k_violation_order_elem_vec diff --git a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp b/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp deleted file mode 100644 index 59c968ca35..0000000000 --- a/tasks/goriacheva_k_violation_order_elem_vec/tests/performance/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include -#include - -#include "goriacheva_k_violation_order_elem_vec/common/include/common.hpp" -#include "goriacheva_k_violation_order_elem_vec/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_violation_order_elem_vec/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" - -namespace goriacheva_k_violation_order_elem_vec { - -class GoriachevaKViolationOrderElemVecPerfTests : public ppc::util::BaseRunPerfTests { - public: - static constexpr std::size_t kPerfSize = 100'000'000; - - protected: - void SetUp() override { - input_.resize(kPerfSize); - - for (std::size_t i = 0; i < kPerfSize; ++i) { - if (i % 3 == 0) { - input_[i] = static_cast(kPerfSize - i); - } else { - input_[i] = static_cast(i % 1000); - } - } - - expected_ = 1; - } - - InType GetTestInputData() final { - return input_; - } - - bool CheckTestOutputData(OutType & /*output_data*/) final { - return true; - } - - private: - InType input_; - OutType expected_{}; -}; - -TEST_P(GoriachevaKViolationOrderElemVecPerfTests, RunPerfModes) { - ExecuteTest(GetParam()); -} - -namespace { -auto BuildPerfParams() { - const auto all_tasks = - ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_goriacheva_k_violation_order_elem_vec); - - return ppc::util::TupleToGTestValues(all_tasks); -} - -const auto kPerfParams = BuildPerfParams(); - -std::string MakePerfName(const ::testing::TestParamInfo &info) { - return GoriachevaKViolationOrderElemVecPerfTests::CustomPerfTestName(info); -} - -INSTANTIATE_TEST_SUITE_P(GoriachevaKViolationOrderElemVecPerfomanceTests, GoriachevaKViolationOrderElemVecPerfTests, - kPerfParams, MakePerfName); - -} // namespace -} // namespace goriacheva_k_violation_order_elem_vec From dd2a33531b66a84af6685f1309498a460ef6992b Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 12:48:27 +0300 Subject: [PATCH 07/21] Add third task --- .../common/include/common.hpp | 16 -- tasks/goriacheva_k_reduce/data/efficiency.png | Bin 55559 -> 0 bytes tasks/goriacheva_k_reduce/data/speedup.png | Bin 54220 -> 0 bytes tasks/goriacheva_k_reduce/data/tests.json | 27 --- .../data/time_vs_processes.png | Bin 71631 -> 0 bytes .../mpi/include/ops_mpi.hpp | 26 --- tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp | 92 -------- tasks/goriacheva_k_reduce/report.md | 182 --------------- .../seq/include/ops_seq.hpp | 22 -- tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp | 38 --- .../tests/functional/main.cpp | 80 ------- .../tests/performance/main.cpp | 31 --- .../common/include/common.hpp | 126 ++++++++++ .../data/tests.json | 17 ++ .../info.json | 2 +- .../mpi/include/ops_mpi.hpp | 25 ++ .../mpi/src/ops_mpi.cpp | 217 ++++++++++++++++++ .../goriacheva_k_strassen_algorithm/report.md | 0 .../seq/include/ops_seq.hpp | 27 +++ .../seq/src/ops_seq.cpp | 48 ++++ .../settings.json | 0 .../tests/.clang-tidy | 0 .../tests/functional/main.cpp | 133 +++++++++++ .../tests/performance/main.cpp | 69 ++++++ 24 files changed, 663 insertions(+), 515 deletions(-) delete mode 100644 tasks/goriacheva_k_reduce/common/include/common.hpp delete mode 100644 tasks/goriacheva_k_reduce/data/efficiency.png delete mode 100644 tasks/goriacheva_k_reduce/data/speedup.png delete mode 100644 tasks/goriacheva_k_reduce/data/tests.json delete mode 100644 tasks/goriacheva_k_reduce/data/time_vs_processes.png delete mode 100644 tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp delete mode 100644 tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp delete mode 100644 tasks/goriacheva_k_reduce/report.md delete mode 100644 tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp delete mode 100644 tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp delete mode 100644 tasks/goriacheva_k_reduce/tests/functional/main.cpp delete mode 100644 tasks/goriacheva_k_reduce/tests/performance/main.cpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/data/tests.json rename tasks/{goriacheva_k_reduce => goriacheva_k_strassen_algorithm}/info.json (88%) create mode 100644 tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/report.md create mode 100644 tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp rename tasks/{goriacheva_k_reduce => goriacheva_k_strassen_algorithm}/settings.json (100%) rename tasks/{goriacheva_k_reduce => goriacheva_k_strassen_algorithm}/tests/.clang-tidy (100%) create mode 100644 tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp create mode 100644 tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp diff --git a/tasks/goriacheva_k_reduce/common/include/common.hpp b/tasks/goriacheva_k_reduce/common/include/common.hpp deleted file mode 100644 index b43df70416..0000000000 --- a/tasks/goriacheva_k_reduce/common/include/common.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "task/include/task.hpp" - -namespace goriacheva_k_reduce { - -using InType = std::vector; -using OutType = std::vector; -using TestType = std::tuple; -using BaseTask = ppc::task::Task; - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/data/efficiency.png b/tasks/goriacheva_k_reduce/data/efficiency.png deleted file mode 100644 index 46c6eb182553ddf8a5968db89736567b1eb24127..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55559 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 z 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�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 G@c#iz1jHNw diff --git a/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp deleted file mode 100644 index 76c6259ad0..0000000000 --- a/tasks/goriacheva_k_reduce/mpi/include/ops_mpi.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include "goriacheva_k_reduce/common/include/common.hpp" -#include "task/include/task.hpp" - -namespace goriacheva_k_reduce { - -class GoriachevaKReduceMPI : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kMPI; - } - explicit GoriachevaKReduceMPI(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::vector local_input_; -}; - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp deleted file mode 100644 index dd44d68ba8..0000000000 --- a/tasks/goriacheva_k_reduce/mpi/src/ops_mpi.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" - -#include - -#include -#include - -#include "goriacheva_k_reduce/common/include/common.hpp" - -namespace goriacheva_k_reduce { - -GoriachevaKReduceMPI::GoriachevaKReduceMPI(const InType &in) { - InType tmp(in); - GetInput().swap(tmp); - SetTypeOfTask(GetStaticTypeOfTask()); -} - -bool GoriachevaKReduceMPI::ValidationImpl() { - return true; -} - -bool GoriachevaKReduceMPI::PreProcessingImpl() { - GetOutput().resize(1); - return true; -} - -bool GoriachevaKReduceMPI::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 = static_cast(GetInput().size()); - } - - MPI_Bcast(&total_size, 1, MPI_INT, 0, MPI_COMM_WORLD); - - if (total_size == 0) { - GetOutput()[0] = 0; - return true; - } - - int base = total_size / size; - int rem = total_size % size; - - int local_size = base + (rank < rem ? 1 : 0); - local_input_.resize(local_size); - - std::vector sendcounts; - std::vector displs; - - if (rank == 0) { - sendcounts.resize(size); - displs.resize(size); - int offset = 0; - for (int i = 0; i < size; ++i) { - sendcounts[i] = base + (i < rem ? 1 : 0); - displs[i] = offset; - offset += sendcounts[i]; - } - } - - MPI_Scatterv(rank == 0 ? GetInput().data() : nullptr, sendcounts.data(), displs.data(), MPI_INT, local_input_.data(), - local_size, MPI_INT, 0, MPI_COMM_WORLD); - - int local_sum = std::accumulate(local_input_.begin(), local_input_.end(), 0); - int global_sum = 0; - - if (rank == 0) { - global_sum = local_sum; - for (int i = 1; i < size; ++i) { - int tmp = 0; - MPI_Recv(&tmp, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - global_sum += tmp; - } - } else { - MPI_Send(&local_sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); - } - - MPI_Bcast(&global_sum, 1, MPI_INT, 0, MPI_COMM_WORLD); - GetOutput()[0] = global_sum; - - return true; -} - -bool GoriachevaKReduceMPI::PostProcessingImpl() { - return true; -} - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/report.md b/tasks/goriacheva_k_reduce/report.md deleted file mode 100644 index f44de52d3e..0000000000 --- a/tasks/goriacheva_k_reduce/report.md +++ /dev/null @@ -1,182 +0,0 @@ -# Передача от всех одному (Reduce) -(последовательная и MPI-реализации) - -Студентка: Горячева Ксения Александровна, группа 3823Б1ФИ2 -Технологии: SEQ, MPI -Вариант: Reduce (Sum) - ---- - -## 1. Введение - -Операция Reduce является одной из базовых коллективных операций в параллельных вычислениях. Её назначение — собрать данные со всех параллельных процессов, применить к ним ассоциативную операцию (в данной работе — суммирование) и передать результат одному процессу (корневому). - -Целью данной работы является разработка и исследование операции Reduce для вычисления суммы элементов целочисленного вектора, а также анализ корректности и производительности реализованных алгоритмов. - ---- - -## 2. Постановка задачи - -Входные данные: -вектор целых чисел std::vector произвольной длины. - -Выходные данные: -вектор длины 1, содержащий сумму всех элементов входного массива. - -Для входного вектора v длины n требуется вычислить: -result = sum_{i=0}^{n-1} v[i] - -### Ограничения и допущения: - -* элементы вектора могут принимать любые значения типа int; -* для пустого вектора результат считается равным 0; -* MPI-реализация должна корректно работать при любом числе процессов. - ---- - -## 3. Базовый алгоритм (Последовательный) - -Последовательный алгоритм является тривиальным. Для нахождения суммы всех элементов вектора используется стандартная функция `std::accumulate` из заголовочного файла ``. Алгоритм итерируется по всем элементам входного вектора, последовательно прибавляя каждый элемент к внутреннему аккумулятору. Начальное значение аккумулятора равно нулю. - -Временная сложность такого алгоритма составляет O(N), где N — количество элементов в векторе. - -## 4. Параллельная реализация (MPI) - -Cемантика операции Reduce: все процессы участвуют в вычислении, итоговая сумма формируется на процессе с рангом 0 и затем рассылается всем процессам. - -### 4.1 Распределение данных - -Пусть: -n — размер входного вектора; -p — число MPI-процессов. - -Размер локального блока для процесса с рангом rank вычисляется следующим образом: -base = n / p rem = n % p local_size = base + (rank < rem ? 1 : 0) - -Процесс с рангом 0 формирует массивы sendcounts и displs, после чего используется коллективная операция: -MPI_Scatterv(...) - -Это позволяет корректно распределить данные даже при n % p ≠ 0. - ---- - -### 4.2 Локальные вычисления - -Каждый процесс вычисляет сумму элементов своего локального блока: -int local_sum = std::accumulate(local_input_.begin(), local_input_.end(), 0); - ---- - -### 4.3 Сбор глобального результата (Reduce) - -Сбор локальных сумм реализован вручную с использованием точечных операций: - -процессы с rank ≠ 0 отправляют свои local_sum на процесс 0 через MPI_Send; -процесс 0 принимает все значения с помощью MPI_Recv и аккумулирует итоговую сумму. - -if (rank == 0) { - global_sum = local_sum; - for (int i = 1; i < size; ++i) { - MPI_Recv(&tmp, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - global_sum += tmp; - } -} else { - MPI_Send(&local_sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); -} - -После этого итоговое значение рассылается всем процессам с помощью MPI_Bcast. - ---- - -## 5. Тестирование корректности - -Для проверки корректности разработан набор функциональных тестов, загружаемых из tests.json. - -Тесты включают: -* небольшой вектор; -* вектор из одного элемента; -* отрицательные значения; -* пустой вектор; -* вектор, заполненный единицами. - -Всего выполнено 10 функциональных тестов (по 5 тест-кейсов для SEQ и MPI реализаций). - -Все тесты успешно пройдены, что подтверждает корректность реализации. - ---- - -## 6. Экспериментальное исследование производительности - -Замеры производительности выполнялись с использованием performance-тестов фреймворка PPC. - -Параметры эксперимента: - -* входные данные: {10'000'000, 1} -* режимы измерений: -* pipeline -* task_run -* количество MPI-процессов: 2, 4, 8, 16, 32 - -### 6.1 Результаты измерений (task_run, MPI) - -Замеры производительности проводились для MPI-реализации на 1, 2, 3, 4, 8 и 16 процессах. За основу для расчетов (`task_run`) взято время выполнения на 1 процессе. - -| Число процессов (P) | Время (сек) | Ускорение (S) | Эффективность (E) | -|---------------------|-------------|---------------|----------------------| -| 1 | 0.00000400 | 1.00 | 1.00 | -| 2 | 0.00000762 | 0.52 | 0.26 | -| 4 | 0.00002508 | 0.16 | 0.04 | -| 8 | 0.00013296 | 0.03 | 0.004 | -| 16 | 0.00654368 | 0.0006 | 0.00004 | -| 32 | 0.01556248 | 0.0003 | 0.000008 | - -Графики производительности - -![График времени выполнения](data/time_vs_processes.png) -*Рис. 1. Зависимость времени выполнения от числа MPI-процессов.* - -![График ускорения](data/speedup.png) -*Рис. 2. Зависимость ускорения от числа MPI-процессов.* - -![График эффективности](data/efficiency.png) -*Рис. 3. Зависимость эффективности от числа MPI-процессов.* - ---- - -## 7. Анализ результатов - -Результаты показывают, что для данной задачи MPI-реализация не демонстрирует ускорения при увеличении числа процессов. - -Основные причины: -* операция суммирования является вычислительно очень простой; -* объём полезных вычислений на процесс резко уменьшается с ростом p; -* накладные расходы на: - MPI_Scatterv, - MPI_Send / MPI_Recv, - MPI_Bcast -начинают доминировать над временем локальных вычислений. - -С увеличением числа процессов время выполнения возрастает, что является наглядной иллюстрацией закона Амдала. - ---- - -## 8. Заключение - -В ходе выполнения работы были реализованы и исследованы последовательная и параллельная версии операции Reduce для вычисления суммы элементов вектора. - -Основные выводы: -* обе реализации корректны и успешно проходят функциональные тесты; -* MPI-версия корректно обрабатывает любые размеры входных данных; -* рост числа процессов приводит к увеличению времени выполнения из-за коммуникационных накладных расходов. - ---- - -## 9. Используемые источники - -1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) -2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) -3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) -4. std::accumulate documentation - [https://en.cppreference.com/w/cpp/algorithm/accumulate](https://en.cppreference.com/w/cpp/algorithm/accumulate) -5. MPI_Reduce documentation - [https://www.open-mpi.org/doc/v4.1/man3/MPI_Reduce.3.php](https://www.open-mpi.org/doc/v4.1/man3/MPI_Reduce.3.php) - ---- \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp b/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp deleted file mode 100644 index e8cf84e8ad..0000000000 --- a/tasks/goriacheva_k_reduce/seq/include/ops_seq.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "goriacheva_k_reduce/common/include/common.hpp" -#include "task/include/task.hpp" - -namespace goriacheva_k_reduce { - -class GoriachevaKReduceSEQ : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; - } - explicit GoriachevaKReduceSEQ(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; -}; - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp b/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp deleted file mode 100644 index 5576667fc7..0000000000 --- a/tasks/goriacheva_k_reduce/seq/src/ops_seq.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "goriacheva_k_reduce//seq/include/ops_seq.hpp" - -#include - -#include "goriacheva_k_reduce//common/include/common.hpp" - -namespace goriacheva_k_reduce { - -GoriachevaKReduceSEQ::GoriachevaKReduceSEQ(const InType &in) { - InType tmp(in); - GetInput().swap(tmp); - SetTypeOfTask(GetStaticTypeOfTask()); -} - -bool GoriachevaKReduceSEQ::ValidationImpl() { - return true; -} - -bool GoriachevaKReduceSEQ::PreProcessingImpl() { - GetOutput().resize(1); - return true; -} - -bool GoriachevaKReduceSEQ::RunImpl() { - const auto input = GetInput(); - if (input.empty()) { - GetOutput()[0] = 0; - return true; - } - GetOutput()[0] = std::accumulate(GetInput().begin(), GetInput().end(), 0); - return true; -} - -bool GoriachevaKReduceSEQ::PostProcessingImpl() { - return true; -} - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/tests/functional/main.cpp b/tasks/goriacheva_k_reduce/tests/functional/main.cpp deleted file mode 100644 index 187297a12e..0000000000 --- a/tasks/goriacheva_k_reduce/tests/functional/main.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "goriacheva_k_reduce/common/include/common.hpp" -#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_reduce/seq/include/ops_seq.hpp" -#include "task/include/task.hpp" -#include "util/include/func_test_util.hpp" -#include "util/include/util.hpp" - -namespace goriacheva_k_reduce { - -using FuncParam = ppc::util::FuncTestParam; - -class GoriachevaKReduceFuncTests : public ppc::util::BaseRunFuncTests { - public: - static std::string PrintTestParam(const testing::TestParamInfo &info) { - const auto &tc = std::get<2>(info.param); - const auto &name = std::get<2>(tc); - return name + "_" + std::to_string(info.index); - } - - protected: - void SetUp() override { - const auto ¶ms = std::get<2>(GetParam()); - input_ = std::get<0>(params); - expected_ = std::get<1>(params); - } - - bool CheckTestOutputData(OutType &output) final { - return output == expected_; - } - - InType GetTestInputData() final { - return input_; - } - - private: - InType input_; - OutType expected_; -}; - -static std::vector LoadTests() { - const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_reduce, "tests.json"); - - std::ifstream fin(path); - nlohmann::json j; - fin >> j; - - std::vector params; - - const std::string settings = PPC_SETTINGS_goriacheva_k_reduce; - const std::string mpi_suffix = ppc::task::GetStringTaskType(GoriachevaKReduceMPI::GetStaticTypeOfTask(), settings); - const std::string seq_suffix = ppc::task::GetStringTaskType(GoriachevaKReduceSEQ::GetStaticTypeOfTask(), settings); - - for (const auto &item : j) { - TestType tc{item.at("input").get(), item.at("result").get(), item.at("name").get()}; - - params.emplace_back(ppc::task::TaskGetter, std::get<2>(tc) + "_" + mpi_suffix, tc); - - params.emplace_back(ppc::task::TaskGetter, std::get<2>(tc) + "_" + seq_suffix, tc); - } - - return params; -} - -const auto kParams = LoadTests(); - -TEST_P(GoriachevaKReduceFuncTests, ReduceSum) { - ExecuteTest(GetParam()); -} - -INSTANTIATE_TEST_SUITE_P(GoriachevaKReduceFunctionalTests, GoriachevaKReduceFuncTests, testing::ValuesIn(kParams), - GoriachevaKReduceFuncTests::PrintTestParam); - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_reduce/tests/performance/main.cpp b/tasks/goriacheva_k_reduce/tests/performance/main.cpp deleted file mode 100644 index cf9c25265a..0000000000 --- a/tasks/goriacheva_k_reduce/tests/performance/main.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include - -#include "goriacheva_k_reduce/common/include/common.hpp" -#include "goriacheva_k_reduce/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_reduce/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" - -namespace goriacheva_k_reduce { - -class GoriachevaKReducePerfTests : public ppc::util::BaseRunPerfTests { - protected: - InType GetTestInputData() final { - return {10'000'000, 1}; - } - - bool CheckTestOutputData(OutType &output) final { - return !output.empty(); - } -}; - -TEST_P(GoriachevaKReducePerfTests, RunPerfModes) { - ExecuteTest(GetParam()); -} - -INSTANTIATE_TEST_SUITE_P( - GoriachevaKReducePerfomanceTests, GoriachevaKReducePerfTests, - ppc::util::TupleToGTestValues(ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_goriacheva_k_reduce)), - GoriachevaKReducePerfTests::CustomPerfTestName); - -} // namespace goriacheva_k_reduce diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp new file mode 100644 index 0000000000..0ee5bc16c1 --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include +#include +#include +#include + +#include "task/include/task.hpp" + +namespace goriacheva_k_strassen_algorithm { + +using Matrix = std::vector>; + +struct InType { + Matrix A; + Matrix B; +}; + +using OutType = Matrix; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +inline bool is_square(const Matrix& M) { + if (M.empty()) return false; + std::size_t n = M.size(); + for (const auto& r : M) + if (r.size() != n) return false; + return true; +} + +inline std::size_t next_power_of_two(std::size_t n) { + std::size_t p = 1; + while (p < n) p <<= 1; + return p; +} + +inline Matrix pad_matrix(const Matrix& A, std::size_t new_size) { + Matrix R(new_size, std::vector(new_size, 0.0)); + for (std::size_t i = 0; i < A.size(); ++i) + for (std::size_t j = 0; j < A.size(); ++j) + R[i][j] = A[i][j]; + return R; +} + +inline Matrix crop_matrix(const Matrix& A, std::size_t size) { + Matrix R(size, std::vector(size)); + for (std::size_t i = 0; i < size; ++i) + for (std::size_t j = 0; j < size; ++j) + R[i][j] = A[i][j]; + return R; +} + +inline Matrix add(const Matrix& A, const Matrix& B) { + std::size_t n = A.size(); + Matrix C(n, std::vector(n)); + for (std::size_t i = 0; i < n; ++i) + for (std::size_t j = 0; j < n; ++j) + C[i][j] = A[i][j] + B[i][j]; + return C; +} + +inline Matrix sub(const Matrix& A, const Matrix& B) { + std::size_t n = A.size(); + Matrix C(n, std::vector(n)); + for (std::size_t i = 0; i < n; ++i) + for (std::size_t j = 0; j < n; ++j) + C[i][j] = A[i][j] - B[i][j]; + return C; +} + +inline Matrix naive_multiply(const Matrix& A, const Matrix& B) { + std::size_t n = A.size(); + Matrix C(n, std::vector(n, 0.0)); + for (std::size_t i = 0; i < n; ++i) + for (std::size_t k = 0; k < n; ++k) + for (std::size_t j = 0; j < n; ++j) + C[i][j] += A[i][k] * B[k][j]; + return C; +} + +inline Matrix strassen(const Matrix& A, const Matrix& B, + std::size_t threshold = 128) { + std::size_t n = A.size(); + if (n <= threshold) + return naive_multiply(A, B); + + std::size_t k = n / 2; + + Matrix A11(k, std::vector(k)), A12(k, std::vector(k)); + Matrix A21(k, std::vector(k)), A22(k, std::vector(k)); + Matrix B11(k, std::vector(k)), B12(k, std::vector(k)); + Matrix B21(k, std::vector(k)), B22(k, std::vector(k)); + + for (std::size_t i = 0; i < k; ++i) + for (std::size_t j = 0; j < k; ++j) { + A11[i][j] = A[i][j]; + A12[i][j] = A[i][j + k]; + A21[i][j] = A[i + k][j]; + A22[i][j] = A[i + k][j + k]; + B11[i][j] = B[i][j]; + B12[i][j] = B[i][j + k]; + B21[i][j] = B[i + k][j]; + B22[i][j] = B[i + k][j + k]; + } + + Matrix M1 = strassen(add(A11, A22), add(B11, B22), threshold); + Matrix M2 = strassen(add(A21, A22), B11, threshold); + Matrix M3 = strassen(A11, sub(B12, B22), threshold); + Matrix M4 = strassen(A22, sub(B21, B11), threshold); + Matrix M5 = strassen(add(A11, A12), B22, threshold); + Matrix M6 = strassen(sub(A21, A11), add(B11, B12), threshold); + Matrix M7 = strassen(sub(A12, A22), add(B21, B22), threshold); + + Matrix C(n, std::vector(n)); + for (std::size_t i = 0; i < k; ++i) + for (std::size_t j = 0; j < k; ++j) { + C[i][j] = M1[i][j] + M4[i][j] - M5[i][j] + M7[i][j]; + C[i][j + k] = M3[i][j] + M5[i][j]; + C[i + k][j] = M2[i][j] + M4[i][j]; + C[i + k][j + k] = M1[i][j] - M2[i][j] + M3[i][j] + M6[i][j]; + } + + return C; +} + +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/data/tests.json b/tasks/goriacheva_k_strassen_algorithm/data/tests.json new file mode 100644 index 0000000000..57a8beffda --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/data/tests.json @@ -0,0 +1,17 @@ +[ + { "name": "1x1_single", "input": { "A": [[7.0]], "B": [[3.0]] }, "result": [[21.0]] }, + { "name": "2x2_simple", "input": { "A": [[1.0,2.0],[3.0,4.0]], "B": [[5.0,6.0],[7.0,8.0]] }, "result": [[19.0,22.0],[43.0,50.0]] }, + { "name": "2x2_zeros", "input": { "A": [[0.0,0.0],[0.0,0.0]], "B": [[1.0,2.0],[3.0,4.0]] }, "result": [[0.0,0.0],[0.0,0.0]] }, + { "name": "2x2_identity", "input": { "A": [[1.0,0.0],[0.0,1.0]], "B": [[2.0,3.0],[4.0,5.0]] }, "result": [[2.0,3.0],[4.0,5.0]] }, + { "name": "3x3_random", "input": { "A": [[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]], "B": [[9.0,8.0,7.0],[6.0,5.0,4.0],[3.0,2.0,1.0]] }, "result": [[30.0,24.0,18.0],[84.0,69.0,54.0],[138.0,114.0,90.0]] }, + { "name": "3x3_identity", "input": { "A": [[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]], "B": [[3.0,2.0,1.0],[6.0,5.0,4.0],[9.0,8.0,7.0]] }, "result": [[3.0,2.0,1.0],[6.0,5.0,4.0],[9.0,8.0,7.0]] }, + { "name": "3x3_diagonal", "input": { "A": [[1.0,0.0,0.0],[0.0,2.0,0.0],[0.0,0.0,3.0]], "B": [[4.0,0.0,0.0],[0.0,5.0,0.0],[0.0,0.0,6.0]] }, "result": [[4.0,0.0,0.0],[0.0,10.0,0.0],[0.0,0.0,18.0]] }, + { "name": "2x2_negatives", "input": { "A": [[-1.0,2.0],[3.0,-4.0]], "B": [[5.0,-6.0],[-7.0,8.0]] }, "result": [[-19.0,22.0],[43.0,-50.0]] }, + { "name": "3x3_repeats", "input": { "A": [[2.0,2.0,2.0],[2.0,2.0,2.0],[2.0,2.0,2.0]], "B": [[1.0,2.0,3.0],[1.0,2.0,3.0],[1.0,2.0,3.0]] }, "result": [[6.0,12.0,18.0],[6.0,12.0,18.0],[6.0,12.0,18.0]] }, + { "name": "3x3_fractional", "input": { "A": [[1.5,2.0,3.5],[4.0,5.0,6.5],[7.5,8.0,9.5]], "B": [[0.5,1.0,1.5],[2.0,2.5,3.0],[3.5,4.0,4.5]] }, "result": [[17.0,20.5,24.0],[34.75,42.5,50.25],[53.0,65.5,78.0]] }, + { "name": "4x4_simple", "input": { "A": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]], "B": [[16.0,15.0,14.0,13.0],[12.0,11.0,10.0,9.0],[8.0,7.0,6.0,5.0],[4.0,3.0,2.0,1.0]] }, "result": [[80.0,70.0,60.0,50.0],[240.0,214.0,188.0,162.0],[400.0,358.0,316.0,274.0],[560.0,502.0,444.0,386.0]] }, + { "name": "4x4_identity", "input": { "A": [[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] }, "result": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] }, + { "name": "4x4_negatives", "input": { "A": [[-1.0,2.0,-3.0,4.0],[5.0,-6.0,7.0,-8.0],[-9.0,10.0,-11.0,12.0],[13.0,-14.0,15.0,-16.0]], "B": [[16.0,-15.0,14.0,-13.0],[-12.0,11.0,-10.0,9.0],[8.0,-7.0,6.0,-5.0],[-4.0,3.0,-2.0,1.0]] }, "result": [[-80.0,70.0,-60.0,50.0],[240.0,-214.0,188.0,-162.0],[-400.0,358.0,-316.0,274.0],[560.0,-502.0,444.0,-386.0]] }, + { "name": "4x4_repeats", "input": { "A": [[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0]], "B": [[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0]] }, "result": [[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0]] }, + { "name": "4x4_fractional", "input": { "A": [[1.5, 2.0, 3.0, 4.5],[5.5, 6.5, 7.0, 8.0],[9.0, 10.5, 11.5, 12.0],[13.0, 14.5, 15.0, 16.5]], "B": [[0.5, 1.0, 1.5, 2.0],[2.5, 3.0, 3.5, 4.0],[4.5, 5.0, 5.5, 6.0],[6.5, 7.0, 7.5, 8.0]] }, "result": [[48.5, 54.0, 59.5, 65.0],[102.5, 116.0, 129.5, 143.0],[160.5, 182.0, 203.5, 225.0],[217.5, 247.0, 276.5, 306.0]] } +] diff --git a/tasks/goriacheva_k_reduce/info.json b/tasks/goriacheva_k_strassen_algorithm/info.json similarity index 88% rename from tasks/goriacheva_k_reduce/info.json rename to tasks/goriacheva_k_strassen_algorithm/info.json index 062e9b0b85..cbe1e07bf7 100644 --- a/tasks/goriacheva_k_reduce/info.json +++ b/tasks/goriacheva_k_strassen_algorithm/info.json @@ -4,6 +4,6 @@ "last_name": "Горячева", "middle_name": "Александровна", "group_number": "3823Б1ФИ2", - "task_number": "2" + "task_number": "3" } } diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..66724eb2f3 --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace goriacheva_k_strassen_algorithm { + +class GoriachevaKStrassenAlgorithmMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit GoriachevaKStrassenAlgorithmMPI(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + InType input_matrices_; + OutType result_matrix_; +}; + +} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..809c1b9b8f --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -0,0 +1,217 @@ +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" + +#include +#include +#include + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" + +namespace goriacheva_k_strassen_algorithm { + +GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI( + const InType& in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; +} + +bool GoriachevaKStrassenAlgorithmMPI::ValidationImpl() { + return is_square(GetInput().A) && + is_square(GetInput().B) && + GetInput().A.size() == GetInput().B.size(); +} + +bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { + input_matrices_ = GetInput(); + return true; +} + +bool GoriachevaKStrassenAlgorithmMPI::RunImpl() { + int rank = 0, size = 1; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + const Matrix& A = input_matrices_.A; + const Matrix& B = input_matrices_.B; + const size_t n = A.size(); + + if (n == 1) { + result_matrix_.assign(1, std::vector(1)); + + if (rank == 0) { + result_matrix_[0][0] = A[0][0] * B[0][0]; + } + + return true; + } + + + // =============================== + // 1. ближайшая степень двойки + // =============================== + size_t m = 1; + if (rank == 0) { + while (m < n) m <<= 1; + } + MPI_Bcast(&m, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD); + + // =============================== + // 2. padding матриц + // =============================== + Matrix Ap(m, std::vector(m, 0.0)); + Matrix Bp(m, std::vector(m, 0.0)); + + if (rank == 0) { + for (size_t i = 0; i < n; ++i) + for (size_t j = 0; j < n; ++j) { + Ap[i][j] = A[i][j]; + Bp[i][j] = B[i][j]; + } + } + + // =============================== + // 3. broadcast padded matrices + // =============================== + for (size_t i = 0; i < m; ++i) { + MPI_Bcast(Ap[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Bcast(Bp[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); + } + + // =============================== + // 4. split matrices + // =============================== + const size_t k = m / 2; + + auto split = [&](const Matrix& M, size_t r, size_t c) { + Matrix out(k, std::vector(k)); + for (size_t i = 0; i < k; ++i) + for (size_t j = 0; j < k; ++j) + out[i][j] = M[i + r * k][j + c * k]; + return out; + }; + + Matrix A11 = split(Ap, 0, 0); + Matrix A12 = split(Ap, 0, 1); + Matrix A21 = split(Ap, 1, 0); + Matrix A22 = split(Ap, 1, 1); + + Matrix B11 = split(Bp, 0, 0); + Matrix B12 = split(Bp, 0, 1); + Matrix B21 = split(Bp, 1, 0); + Matrix B22 = split(Bp, 1, 1); + + // =============================== + // 5. инициализация M1–M7 + // =============================== + Matrix zero(k, std::vector(k, 0.0)); + Matrix M1 = zero, M2 = zero, M3 = zero, M4 = zero; + Matrix M5 = zero, M6 = zero, M7 = zero; + + // =============================== + // 6. распределение задач + // =============================== + int task = rank % 7; + + if (task == 0) + M1 = naive_multiply(add(A11, A22), add(B11, B22)); + if (task == 1) + M2 = naive_multiply(add(A21, A22), B11); + if (task == 2) + M3 = naive_multiply(A11, sub(B12, B22)); + if (task == 3) + M4 = naive_multiply(A22, sub(B21, B11)); + if (task == 4) + M5 = naive_multiply(add(A11, A12), B22); + if (task == 5) + M6 = naive_multiply(sub(A21, A11), add(B11, B12)); + if (task == 6) + M7 = naive_multiply(sub(A12, A22), add(B21, B22)); + +// =============================== + // 7. корректный MPI_Reduce + // =============================== + auto flatten = [&](const Matrix& M) { + std::vector v(k * k); + for (size_t i = 0; i < k; ++i) + for (size_t j = 0; j < k; ++j) + v[i * k + j] = M[i][j]; + return v; + }; + + auto unflatten = [&](const std::vector& v) { + Matrix M(k, std::vector(k)); + for (size_t i = 0; i < k; ++i) + for (size_t j = 0; j < k; ++j) + M[i][j] = v[i * k + j]; + return M; + }; + + auto reduce_matrix = [&](Matrix& M) { + std::vector send = flatten(M); + std::vector recv(k * k, 0.0); + + MPI_Reduce(send.data(), recv.data(), + static_cast(k * k), + MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); + if (rank == 0) + M = unflatten(recv); + }; + + reduce_matrix(M1); + reduce_matrix(M2); + reduce_matrix(M3); + reduce_matrix(M4); + reduce_matrix(M5); + reduce_matrix(M6); + reduce_matrix(M7); + + // =============================== + // 8. сборка результата + // =============================== + Matrix Cp(m, std::vector(m, 0.0)); + + if (rank == 0) { + Matrix C11 = add(sub(add(M1, M4), M5), M7); + Matrix C12 = add(M3, M5); + Matrix C21 = add(M2, M4); + Matrix C22 = add(sub(add(M1, M3), M2), M6); + + for (size_t i = 0; i < k; ++i) + for (size_t j = 0; j < k; ++j) { + Cp[i][j] = C11[i][j]; + Cp[i][j + k] = C12[i][j]; + Cp[i + k][j] = C21[i][j]; + Cp[i + k][j + k] = C22[i][j]; + } + } + + // =============================== + // 9. broadcast результата + // =============================== + for (size_t i = 0; i < m; ++i) + MPI_Bcast(Cp[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + // =============================== + // 10. обрезка + // =============================== + result_matrix_.assign(n, std::vector(n)); + for (size_t i = 0; i < n; ++i) + for (size_t j = 0; j < n; ++j) + result_matrix_[i][j] = Cp[i][j]; + + return true; +} + +bool GoriachevaKStrassenAlgorithmMPI::PostProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + GetOutput() = result_matrix_; + }else{ + GetOutput().clear(); + } + + return true; +} + +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/report.md b/tasks/goriacheva_k_strassen_algorithm/report.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..a4ed41e6de --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace goriacheva_k_strassen_algorithm { + +class GoriachevaKStrassenAlgorithmSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit GoriachevaKStrassenAlgorithmSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + InType input_matrices_; + OutType result_matrix_; +}; + +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..d60224df8d --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -0,0 +1,48 @@ +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" + +#include + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" + + +namespace goriacheva_k_strassen_algorithm { + +GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ( + const InType& in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; +} + +bool GoriachevaKStrassenAlgorithmSEQ::ValidationImpl() { + return is_square(GetInput().A) && + is_square(GetInput().B) && + GetInput().A.size() == GetInput().B.size(); +} + +bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { + input_matrices_ = GetInput(); + return true; +} + +bool GoriachevaKStrassenAlgorithmSEQ::RunImpl() { + const auto& A = input_matrices_.A; + const auto& B = input_matrices_.B; + + std::size_t n = A.size(); + std::size_t m = next_power_of_two(n); + + Matrix A_pad = (n == m) ? A : pad_matrix(A, m); + Matrix B_pad = (n == m) ? B : pad_matrix(B, m); + + Matrix C_pad = strassen(A_pad, B_pad); + result_matrix_ = (n == m) ? C_pad : crop_matrix(C_pad, n); + + return true; +} + +bool GoriachevaKStrassenAlgorithmSEQ::PostProcessingImpl() { + GetOutput() = result_matrix_; + return true; +} + +} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file diff --git a/tasks/goriacheva_k_reduce/settings.json b/tasks/goriacheva_k_strassen_algorithm/settings.json similarity index 100% rename from tasks/goriacheva_k_reduce/settings.json rename to tasks/goriacheva_k_strassen_algorithm/settings.json diff --git a/tasks/goriacheva_k_reduce/tests/.clang-tidy b/tasks/goriacheva_k_strassen_algorithm/tests/.clang-tidy similarity index 100% rename from tasks/goriacheva_k_reduce/tests/.clang-tidy rename to tasks/goriacheva_k_strassen_algorithm/tests/.clang-tidy diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp new file mode 100644 index 0000000000..c8608a0ac6 --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -0,0 +1,133 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include "task/include/task.hpp" +#include "util/include/func_test_util.hpp" + +namespace goriacheva_k_strassen_algorithm { + +using FuncParam = ppc::util::FuncTestParam; + +class GoriachevaKStrassenAlgorithmFuncTests + : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const testing::TestParamInfo& info) { + return std::get( + ppc::util::GTestParamIndex::kNameTest)>(info.param); + } + + protected: + void SetUp() override { + const auto& params = + std::get( + ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_ = std::get<0>(params); + expected_ = std::get<1>(params); + } + + InType GetTestInputData() final { + return input_; + } + + bool CheckTestOutputData(OutType& output_data) final { + if (output_data.size() != expected_.size()) return false; + + for (std::size_t i = 0; i < expected_.size(); ++i) { + if (output_data[i].size() != expected_[i].size()) return false; + for (std::size_t j = 0; j < expected_[i].size(); ++j) { + if (std::fabs(output_data[i][j] - expected_[i][j]) > 1e-6) { + return false; + } + } + } + return true; + } + + private: + InType input_; + OutType expected_; +}; + +namespace { + +std::vector LoadTestParams() { + const std::string path = + ppc::util::GetAbsoluteTaskPath( + PPC_ID_goriacheva_k_strassen_algorithm, "tests.json"); + + std::ifstream fin(path); + if (!fin.is_open()) { + throw std::runtime_error("Cannot open tests.json"); + } + + nlohmann::json j; + fin >> j; + + std::vector cases; + cases.reserve(j.size() * 2); + + const std::string settings_path = + PPC_SETTINGS_goriacheva_k_strassen_algorithm; + + const std::string mpi_suffix = + ppc::task::GetStringTaskType( + GoriachevaKStrassenAlgorithmMPI::GetStaticTypeOfTask(), + settings_path); + + const std::string seq_suffix = + ppc::task::GetStringTaskType( + GoriachevaKStrassenAlgorithmSEQ::GetStaticTypeOfTask(), + settings_path); + + for (const auto& item : j) { + InType input; + input.A = item.at("input").at("A").get>>(); + input.B = item.at("input").at("B").get>>(); + + OutType expected = + item.at("result").get(); + + TestType tc{ + input, + expected, + item.at("name").get() + }; + + std::string mpi_name = std::get<2>(tc) + "_" + mpi_suffix; + cases.emplace_back( + ppc::task::TaskGetter, + mpi_name, tc); + + std::string seq_name = std::get<2>(tc) + "_" + seq_suffix; + cases.emplace_back( + ppc::task::TaskGetter, + seq_name, tc); + } + + return cases; +} + +const std::vector kFuncParams = LoadTestParams(); + +TEST_P(GoriachevaKStrassenAlgorithmFuncTests, MatrixMultiplication) { + ExecuteTest(GetParam()); +} + +INSTANTIATE_TEST_SUITE_P( + GoriachevaKStrassenAlgorithmFunctionalTests, + GoriachevaKStrassenAlgorithmFuncTests, + testing::ValuesIn(kFuncParams), + GoriachevaKStrassenAlgorithmFuncTests::PrintTestParam); + +} // namespace +} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp new file mode 100644 index 0000000000..d7964fc99a --- /dev/null +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -0,0 +1,69 @@ +#include + +#include +#include +#include + +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace goriacheva_k_strassen_algorithm { + +class GoriachevaKStrassenAlgorithmPerfTests + : public ppc::util::BaseRunPerfTests { + public: + static constexpr std::size_t kMatrixSize = 256; + + protected: + void SetUp() override { + input_.A.assign(kMatrixSize, std::vector(kMatrixSize, 1.0)); + input_.B.assign(kMatrixSize, std::vector(kMatrixSize, 2.0)); + } + + InType GetTestInputData() final { + return input_; + } + + bool CheckTestOutputData(OutType& /*output_data*/) final { + return true; // perf-тесты не проверяют корректность + } + + private: + InType input_; +}; + +TEST_P(GoriachevaKStrassenAlgorithmPerfTests, RunPerfModes) { + ExecuteTest(GetParam()); +} + +namespace { + +auto BuildPerfParams() { + const auto all_tasks = + ppc::util::MakeAllPerfTasks< + InType, + GoriachevaKStrassenAlgorithmMPI, + GoriachevaKStrassenAlgorithmSEQ>( + PPC_SETTINGS_goriacheva_k_strassen_algorithm); + + return ppc::util::TupleToGTestValues(all_tasks); +} + +const auto kPerfParams = BuildPerfParams(); + +std::string MakePerfName( + const ::testing::TestParamInfo< + GoriachevaKStrassenAlgorithmPerfTests::ParamType>& info) { + return GoriachevaKStrassenAlgorithmPerfTests::CustomPerfTestName(info); +} + +INSTANTIATE_TEST_SUITE_P( + GoriachevaKStrassenAlgorithmPerfomanceTests, + GoriachevaKStrassenAlgorithmPerfTests, + kPerfParams, + MakePerfName); + +} // namespace +} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file From 64a8fbce629a98dbe1b6434612fc592a041205b5 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 17:13:56 +0300 Subject: [PATCH 08/21] Add third task --- .../common/include/common.hpp | 97 ++++-- .../data/efficiency.png | Bin 0 -> 61173 bytes .../data/speedup.png | Bin 0 -> 58539 bytes .../data/tests.json | 3 +- .../data/time_vs_processes.png | Bin 0 -> 73523 bytes .../mpi/include/ops_mpi.hpp | 23 +- .../mpi/src/ops_mpi.cpp | 302 ++++++++---------- .../goriacheva_k_strassen_algorithm/report.md | 198 ++++++++++++ .../seq/src/ops_seq.cpp | 14 +- .../tests/functional/main.cpp | 67 ++-- .../tests/performance/main.cpp | 23 +- 11 files changed, 455 insertions(+), 272 deletions(-) create mode 100644 tasks/goriacheva_k_strassen_algorithm/data/efficiency.png create mode 100644 tasks/goriacheva_k_strassen_algorithm/data/speedup.png create mode 100644 tasks/goriacheva_k_strassen_algorithm/data/time_vs_processes.png diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 0ee5bc16c1..a2d63104ef 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -20,69 +20,106 @@ using OutType = Matrix; using TestType = std::tuple; using BaseTask = ppc::task::Task; -inline bool is_square(const Matrix& M) { - if (M.empty()) return false; +inline std::vector flatten(const Matrix &M) { + std::vector buf; + buf.reserve(M.size() * M.size()); + for (const auto &row : M) { + buf.insert(buf.end(), row.begin(), row.end()); + } + return buf; +} + +inline Matrix unflatten(const std::vector &buf, std::size_t n) { + Matrix M(n, std::vector(n)); + for (std::size_t i = 0; i < n; ++i) { + for (std::size_t j = 0; j < n; ++j) { + M[i][j] = buf[i * n + j]; + } + } + return M; +} + +inline bool is_square(const Matrix &M) { + if (M.empty()) { + return false; + } std::size_t n = M.size(); - for (const auto& r : M) - if (r.size() != n) return false; + for (const auto &r : M) { + if (r.size() != n) { + return false; + } + } return true; } inline std::size_t next_power_of_two(std::size_t n) { std::size_t p = 1; - while (p < n) p <<= 1; + while (p < n) { + p <<= 1; + } return p; } -inline Matrix pad_matrix(const Matrix& A, std::size_t new_size) { +inline Matrix pad_matrix(const Matrix &A, std::size_t new_size) { Matrix R(new_size, std::vector(new_size, 0.0)); - for (std::size_t i = 0; i < A.size(); ++i) - for (std::size_t j = 0; j < A.size(); ++j) + for (std::size_t i = 0; i < A.size(); ++i) { + for (std::size_t j = 0; j < A.size(); ++j) { R[i][j] = A[i][j]; + } + } return R; } -inline Matrix crop_matrix(const Matrix& A, std::size_t size) { +inline Matrix crop_matrix(const Matrix &A, std::size_t size) { Matrix R(size, std::vector(size)); - for (std::size_t i = 0; i < size; ++i) - for (std::size_t j = 0; j < size; ++j) + for (std::size_t i = 0; i < size; ++i) { + for (std::size_t j = 0; j < size; ++j) { R[i][j] = A[i][j]; + } + } return R; } -inline Matrix add(const Matrix& A, const Matrix& B) { +inline Matrix add(const Matrix &A, const Matrix &B) { std::size_t n = A.size(); Matrix C(n, std::vector(n)); - for (std::size_t i = 0; i < n; ++i) - for (std::size_t j = 0; j < n; ++j) + for (std::size_t i = 0; i < n; ++i) { + for (std::size_t j = 0; j < n; ++j) { C[i][j] = A[i][j] + B[i][j]; + } + } return C; } -inline Matrix sub(const Matrix& A, const Matrix& B) { +inline Matrix sub(const Matrix &A, const Matrix &B) { std::size_t n = A.size(); Matrix C(n, std::vector(n)); - for (std::size_t i = 0; i < n; ++i) - for (std::size_t j = 0; j < n; ++j) + for (std::size_t i = 0; i < n; ++i) { + for (std::size_t j = 0; j < n; ++j) { C[i][j] = A[i][j] - B[i][j]; + } + } return C; } -inline Matrix naive_multiply(const Matrix& A, const Matrix& B) { +inline Matrix naive_multiply(const Matrix &A, const Matrix &B) { std::size_t n = A.size(); Matrix C(n, std::vector(n, 0.0)); - for (std::size_t i = 0; i < n; ++i) - for (std::size_t k = 0; k < n; ++k) - for (std::size_t j = 0; j < n; ++j) + for (std::size_t i = 0; i < n; ++i) { + for (std::size_t k = 0; k < n; ++k) { + for (std::size_t j = 0; j < n; ++j) { C[i][j] += A[i][k] * B[k][j]; + } + } + } return C; } -inline Matrix strassen(const Matrix& A, const Matrix& B, - std::size_t threshold = 128) { +inline Matrix strassen(const Matrix &A, const Matrix &B, std::size_t threshold = 128) { std::size_t n = A.size(); - if (n <= threshold) + if (n <= threshold) { return naive_multiply(A, B); + } std::size_t k = n / 2; @@ -91,7 +128,7 @@ inline Matrix strassen(const Matrix& A, const Matrix& B, Matrix B11(k, std::vector(k)), B12(k, std::vector(k)); Matrix B21(k, std::vector(k)), B22(k, std::vector(k)); - for (std::size_t i = 0; i < k; ++i) + for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { A11[i][j] = A[i][j]; A12[i][j] = A[i][j + k]; @@ -102,6 +139,7 @@ inline Matrix strassen(const Matrix& A, const Matrix& B, B21[i][j] = B[i + k][j]; B22[i][j] = B[i + k][j + k]; } + } Matrix M1 = strassen(add(A11, A22), add(B11, B22), threshold); Matrix M2 = strassen(add(A21, A22), B11, threshold); @@ -112,13 +150,14 @@ inline Matrix strassen(const Matrix& A, const Matrix& B, Matrix M7 = strassen(sub(A12, A22), add(B21, B22), threshold); Matrix C(n, std::vector(n)); - for (std::size_t i = 0; i < k; ++i) + for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { - C[i][j] = M1[i][j] + M4[i][j] - M5[i][j] + M7[i][j]; - C[i][j + k] = M3[i][j] + M5[i][j]; - C[i + k][j] = M2[i][j] + M4[i][j]; + C[i][j] = M1[i][j] + M4[i][j] - M5[i][j] + M7[i][j]; + C[i][j + k] = M3[i][j] + M5[i][j]; + C[i + k][j] = M2[i][j] + M4[i][j]; C[i + k][j + k] = M1[i][j] - M2[i][j] + M3[i][j] + M6[i][j]; } + } return C; } diff --git a/tasks/goriacheva_k_strassen_algorithm/data/efficiency.png b/tasks/goriacheva_k_strassen_algorithm/data/efficiency.png new file mode 100644 index 0000000000000000000000000000000000000000..97ddfa08ecfb0a7b7f4f766c90361b7a43ad30e4 GIT binary patch literal 61173 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

mzpPi5kL)+++MP%?iBT|v0Yjoi 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 T`IU&m5rl<_jd9IUkEs6w!fgM7 literal 0 HcmV?d00001 diff --git a/tasks/goriacheva_k_strassen_algorithm/data/speedup.png b/tasks/goriacheva_k_strassen_algorithm/data/speedup.png new file mode 100644 index 0000000000000000000000000000000000000000..c1f8947357569cfd81953846735ff9a28c930aab GIT binary patch literal 58539 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
;TNH?;chh*H=+Gx0xJbxMb>19N$DvirPUC$tJ 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 literal 0 HcmV?d00001 diff --git a/tasks/goriacheva_k_strassen_algorithm/data/tests.json b/tasks/goriacheva_k_strassen_algorithm/data/tests.json index 57a8beffda..9efb7c60b9 100644 --- a/tasks/goriacheva_k_strassen_algorithm/data/tests.json +++ b/tasks/goriacheva_k_strassen_algorithm/data/tests.json @@ -13,5 +13,6 @@ { "name": "4x4_identity", "input": { "A": [[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] }, "result": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] }, { "name": "4x4_negatives", "input": { "A": [[-1.0,2.0,-3.0,4.0],[5.0,-6.0,7.0,-8.0],[-9.0,10.0,-11.0,12.0],[13.0,-14.0,15.0,-16.0]], "B": [[16.0,-15.0,14.0,-13.0],[-12.0,11.0,-10.0,9.0],[8.0,-7.0,6.0,-5.0],[-4.0,3.0,-2.0,1.0]] }, "result": [[-80.0,70.0,-60.0,50.0],[240.0,-214.0,188.0,-162.0],[-400.0,358.0,-316.0,274.0],[560.0,-502.0,444.0,-386.0]] }, { "name": "4x4_repeats", "input": { "A": [[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0]], "B": [[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0]] }, "result": [[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0]] }, - { "name": "4x4_fractional", "input": { "A": [[1.5, 2.0, 3.0, 4.5],[5.5, 6.5, 7.0, 8.0],[9.0, 10.5, 11.5, 12.0],[13.0, 14.5, 15.0, 16.5]], "B": [[0.5, 1.0, 1.5, 2.0],[2.5, 3.0, 3.5, 4.0],[4.5, 5.0, 5.5, 6.0],[6.5, 7.0, 7.5, 8.0]] }, "result": [[48.5, 54.0, 59.5, 65.0],[102.5, 116.0, 129.5, 143.0],[160.5, 182.0, 203.5, 225.0],[217.5, 247.0, 276.5, 306.0]] } + { "name": "4x4_fractional", "input": { "A": [[1.5, 2.0, 3.0, 4.5],[5.5, 6.5, 7.0, 8.0],[9.0, 10.5, 11.5, 12.0],[13.0, 14.5, 15.0, 16.5]], "B": [[0.5, 1.0, 1.5, 2.0],[2.5, 3.0, 3.5, 4.0],[4.5, 5.0, 5.5, 6.0],[6.5, 7.0, 7.5, 8.0]] }, "result": [[48.5, 54.0, 59.5, 65.0],[102.5, 116.0, 129.5, 143.0],[160.5, 182.0, 203.5, 225.0],[217.5, 247.0, 276.5, 306.0]] }, + { "name": "5x5_identity", "input": { "A": [[1.0,0.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0,0.0],[0.0,0.0,1.0,0.0,0.0],[0.0,0.0,0.0,1.0,0.0],[0.0,0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] }, "result": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] } ] diff --git a/tasks/goriacheva_k_strassen_algorithm/data/time_vs_processes.png b/tasks/goriacheva_k_strassen_algorithm/data/time_vs_processes.png new file mode 100644 index 0000000000000000000000000000000000000000..989ddf099c8ed0380fd54c2f88b9130e6f5024d3 GIT binary patch literal 73523 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 k + +#include + #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" @@ -10,16 +14,19 @@ class GoriachevaKStrassenAlgorithmMPI : public BaseTask { static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { return ppc::task::TypeOfTask::kMPI; } + explicit GoriachevaKStrassenAlgorithmMPI(const InType &in); - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + InType input_matrices_; + OutType result_matrix_; - InType input_matrices_; - OutType result_matrix_; + Matrix mpi_strassen_top(const Matrix &A, const Matrix &B); }; -} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index 809c1b9b8f..9b3a353f01 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -1,23 +1,21 @@ #include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" #include -#include + #include +#include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" namespace goriacheva_k_strassen_algorithm { -GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI( - const InType& in) { +GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; } bool GoriachevaKStrassenAlgorithmMPI::ValidationImpl() { - return is_square(GetInput().A) && - is_square(GetInput().B) && - GetInput().A.size() == GetInput().B.size(); + return is_square(GetInput().A) && is_square(GetInput().B) && GetInput().A.size() == GetInput().B.size(); } bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { @@ -25,192 +23,164 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { return true; } -bool GoriachevaKStrassenAlgorithmMPI::RunImpl() { - int rank = 0, size = 1; +Matrix GoriachevaKStrassenAlgorithmMPI::mpi_strassen_top(const Matrix &A, const Matrix &B) { + int rank = 0; + int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - const Matrix& A = input_matrices_.A; - const Matrix& B = input_matrices_.B; - const size_t n = A.size(); - - if (n == 1) { - result_matrix_.assign(1, std::vector(1)); + std::size_t n = A.size(); + if (size == 1 || n <= 1) { + return strassen(A, B); + } - if (rank == 0) { - result_matrix_[0][0] = A[0][0] * B[0][0]; + std::size_t k = n / 2; + + Matrix A11(k, std::vector(k)), A12(k, std::vector(k)); + Matrix A21(k, std::vector(k)), A22(k, std::vector(k)); + Matrix B11(k, std::vector(k)), B12(k, std::vector(k)); + Matrix B21(k, std::vector(k)), B22(k, std::vector(k)); + + for (std::size_t i = 0; i < k; ++i) { + for (std::size_t j = 0; j < k; ++j) { + A11[i][j] = A[i][j]; + A12[i][j] = A[i][j + k]; + A21[i][j] = A[i + k][j]; + A22[i][j] = A[i + k][j + k]; + B11[i][j] = B[i][j]; + B12[i][j] = B[i][j + k]; + B21[i][j] = B[i + k][j]; + B22[i][j] = B[i + k][j + k]; } + } - return true; + int num_tasks = std::min(7, size); + int task_id = rank % num_tasks; + + MPI_Comm subcomm; + MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &subcomm); + + int sub_rank; + MPI_Comm_rank(subcomm, &sub_rank); + + Matrix Mi; + if (sub_rank == 0) { + switch (task_id) { + case 0: + Mi = strassen(add(A11, A22), add(B11, B22)); + break; + case 1: + Mi = strassen(add(A21, A22), B11); + break; + case 2: + Mi = strassen(A11, sub(B12, B22)); + break; + case 3: + Mi = strassen(A22, sub(B21, B11)); + break; + case 4: + Mi = strassen(add(A11, A12), B22); + break; + case 5: + Mi = strassen(sub(A21, A11), add(B11, B12)); + break; + case 6: + Mi = strassen(sub(A12, A22), add(B21, B22)); + break; + } } + MPI_Comm_free(&subcomm); + + std::vector M(7); - // =============================== - // 1. ближайшая степень двойки - // =============================== - size_t m = 1; if (rank == 0) { - while (m < n) m <<= 1; - } - MPI_Bcast(&m, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD); + if (task_id < num_tasks && sub_rank == 0) { + M[task_id] = Mi; + } - // =============================== - // 2. padding матриц - // =============================== - Matrix Ap(m, std::vector(m, 0.0)); - Matrix Bp(m, std::vector(m, 0.0)); + for (int i = 1; i < num_tasks; ++i) { + int tid; + std::vector buf(k * k); + MPI_Status status; - if (rank == 0) { - for (size_t i = 0; i < n; ++i) - for (size_t j = 0; j < n; ++j) { - Ap[i][j] = A[i][j]; - Bp[i][j] = B[i][j]; + MPI_Recv(&tid, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status); + MPI_Recv(buf.data(), k * k, MPI_DOUBLE, status.MPI_SOURCE, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + M[tid] = unflatten(buf, k); + } + + for (int t = num_tasks; t < 7; ++t) { + switch (t) { + case 0: + M[0] = strassen(add(A11, A22), add(B11, B22)); + break; + case 1: + M[1] = strassen(add(A21, A22), B11); + break; + case 2: + M[2] = strassen(A11, sub(B12, B22)); + break; + case 3: + M[3] = strassen(A22, sub(B21, B11)); + break; + case 4: + M[4] = strassen(add(A11, A12), B22); + break; + case 5: + M[5] = strassen(sub(A21, A11), add(B11, B12)); + break; + case 6: + M[6] = strassen(sub(A12, A22), add(B21, B22)); + break; } + } + } else if (sub_rank == 0) { + auto buf = flatten(Mi); + MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); + MPI_Send(buf.data(), k * k, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); } - // =============================== - // 3. broadcast padded matrices - // =============================== - for (size_t i = 0; i < m; ++i) { - MPI_Bcast(Ap[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); - MPI_Bcast(Bp[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); + Matrix C(n, std::vector(n)); + if (rank == 0) { + for (std::size_t i = 0; i < k; ++i) { + for (std::size_t j = 0; j < k; ++j) { + C[i][j] = M[0][i][j] + M[3][i][j] - M[4][i][j] + M[6][i][j]; + C[i][j + k] = M[2][i][j] + M[4][i][j]; + C[i + k][j] = M[1][i][j] + M[3][i][j]; + C[i + k][j + k] = M[0][i][j] - M[1][i][j] + M[2][i][j] + M[5][i][j]; + } + } } - // =============================== - // 4. split matrices - // =============================== - const size_t k = m / 2; - - auto split = [&](const Matrix& M, size_t r, size_t c) { - Matrix out(k, std::vector(k)); - for (size_t i = 0; i < k; ++i) - for (size_t j = 0; j < k; ++j) - out[i][j] = M[i + r * k][j + c * k]; - return out; - }; - - Matrix A11 = split(Ap, 0, 0); - Matrix A12 = split(Ap, 0, 1); - Matrix A21 = split(Ap, 1, 0); - Matrix A22 = split(Ap, 1, 1); - - Matrix B11 = split(Bp, 0, 0); - Matrix B12 = split(Bp, 0, 1); - Matrix B21 = split(Bp, 1, 0); - Matrix B22 = split(Bp, 1, 1); - - // =============================== - // 5. инициализация M1–M7 - // =============================== - Matrix zero(k, std::vector(k, 0.0)); - Matrix M1 = zero, M2 = zero, M3 = zero, M4 = zero; - Matrix M5 = zero, M6 = zero, M7 = zero; - - // =============================== - // 6. распределение задач - // =============================== - int task = rank % 7; - - if (task == 0) - M1 = naive_multiply(add(A11, A22), add(B11, B22)); - if (task == 1) - M2 = naive_multiply(add(A21, A22), B11); - if (task == 2) - M3 = naive_multiply(A11, sub(B12, B22)); - if (task == 3) - M4 = naive_multiply(A22, sub(B21, B11)); - if (task == 4) - M5 = naive_multiply(add(A11, A12), B22); - if (task == 5) - M6 = naive_multiply(sub(A21, A11), add(B11, B12)); - if (task == 6) - M7 = naive_multiply(sub(A12, A22), add(B21, B22)); - -// =============================== - // 7. корректный MPI_Reduce - // =============================== - auto flatten = [&](const Matrix& M) { - std::vector v(k * k); - for (size_t i = 0; i < k; ++i) - for (size_t j = 0; j < k; ++j) - v[i * k + j] = M[i][j]; - return v; - }; - - auto unflatten = [&](const std::vector& v) { - Matrix M(k, std::vector(k)); - for (size_t i = 0; i < k; ++i) - for (size_t j = 0; j < k; ++j) - M[i][j] = v[i * k + j]; - return M; - }; - - auto reduce_matrix = [&](Matrix& M) { - std::vector send = flatten(M); - std::vector recv(k * k, 0.0); - - MPI_Reduce(send.data(), recv.data(), - static_cast(k * k), - MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); - if (rank == 0) - M = unflatten(recv); - }; - - reduce_matrix(M1); - reduce_matrix(M2); - reduce_matrix(M3); - reduce_matrix(M4); - reduce_matrix(M5); - reduce_matrix(M6); - reduce_matrix(M7); - - // =============================== - // 8. сборка результата - // =============================== - Matrix Cp(m, std::vector(m, 0.0)); + auto flatC = flatten(C); + MPI_Bcast(flatC.data(), n * n, MPI_DOUBLE, 0, MPI_COMM_WORLD); - if (rank == 0) { - Matrix C11 = add(sub(add(M1, M4), M5), M7); - Matrix C12 = add(M3, M5); - Matrix C21 = add(M2, M4); - Matrix C22 = add(sub(add(M1, M3), M2), M6); - - for (size_t i = 0; i < k; ++i) - for (size_t j = 0; j < k; ++j) { - Cp[i][j] = C11[i][j]; - Cp[i][j + k] = C12[i][j]; - Cp[i + k][j] = C21[i][j]; - Cp[i + k][j + k] = C22[i][j]; - } + if (rank != 0) { + C = unflatten(flatC, n); } - // =============================== - // 9. broadcast результата - // =============================== - for (size_t i = 0; i < m; ++i) - MPI_Bcast(Cp[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD); + return C; +} + +bool GoriachevaKStrassenAlgorithmMPI::RunImpl() { + const auto &A = input_matrices_.A; + const auto &B = input_matrices_.B; - // =============================== - // 10. обрезка - // =============================== - result_matrix_.assign(n, std::vector(n)); - for (size_t i = 0; i < n; ++i) - for (size_t j = 0; j < n; ++j) - result_matrix_[i][j] = Cp[i][j]; + std::size_t n = A.size(); + std::size_t m = next_power_of_two(n); + + Matrix A_pad = (n == m) ? A : pad_matrix(A, m); + Matrix B_pad = (n == m) ? B : pad_matrix(B, m); + + Matrix C_pad = mpi_strassen_top(A_pad, B_pad); + result_matrix_ = (n == m) ? C_pad : crop_matrix(C_pad, n); return true; } bool GoriachevaKStrassenAlgorithmMPI::PostProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - if (rank == 0) { - GetOutput() = result_matrix_; - }else{ - GetOutput().clear(); - } - + GetOutput() = result_matrix_; return true; } diff --git a/tasks/goriacheva_k_strassen_algorithm/report.md b/tasks/goriacheva_k_strassen_algorithm/report.md index e69de29bb2..6e25be7166 100644 --- a/tasks/goriacheva_k_strassen_algorithm/report.md +++ b/tasks/goriacheva_k_strassen_algorithm/report.md @@ -0,0 +1,198 @@ +# Умножение плотных матриц. Элементы типа double. Алгоритм Штрассена. +(последовательная и MPI-реализации, алгоритм Штрассена) + +Студентка: Горячева Ксения Александровна, группа 3823Б1ФИ2 +Технологии: SEQ, MPI +Вариант: №3 + +--- + +## 1. Введение +Задача умножения матриц является одной из базовых и наиболее часто встречающихся задач линейной алгебры и численных методов. Она широко применяется в научных вычислениях, компьютерной графике, машинном обучении и обработке сигналов. + +Классический алгоритм умножения квадратных матриц имеет вычислительную сложность +O(n³), что делает его неэффективным для матриц большого размера. Одним из способов оптимизации является использование алгоритма Штрассена, который уменьшает асимптотическую сложность до O(n^{log₂7}) ≈ O(n^{2.81}) за счёт сокращения количества умножений. + +Целью данной работы является реализация и исследование последовательной и параллельной (MPI) версий алгоритма Штрассена для умножения плотных квадратных матриц с элементами типа double. + +--- + +## 2. Постановка задачи + +Входные данные: +Две квадратные матрицы A и B размера n × n, элементы типа double. + +Выходные данные: +Матрица C = A × B размера n × n. + +Ограничения и допущения: +* матрицы являются квадратными и одинакового размера; +* размер матриц может не быть степенью двойки; +* элементы матриц имеют тип double; +* результаты SEQ и MPI реализаций должны совпадать с точностью 1e-6. + +--- + +## 3. Последовательная реализация (SEQ) + +### 3.1 Общая идея + +Последовательная версия основана на рекурсивной реализации алгоритма Штрассена. +Если размер матрицы превышает заданный порог (threshold = 128), матрица разбивается на 4 подматрицы, после чего вычисляются 7 вспомогательных матриц вместо 8, как в классическом блочном алгоритме. +Для малых размеров используется наивное умножение, так как оно эффективнее из-за меньших накладных расходов. + +--- + +### 3.2 Дополнение матриц + +Алгоритм Штрассена требует, чтобы размер матрицы был степенью двойки. +Если это не так, матрицы дополняются нулями до ближайшей степени двойки: +m = next_power_of_two(n) +После вычислений результат обрезается до исходного размера. + +--- + +### 3.3 Наивное умножение + +При достижении порога рекурсии используется стандартный алгоритм: +for i + for k + for j + C[i][j] += A[i][k] * B[k][j] + +--- + +### 3.4 Сложность + +* по времени: + * асимптотически — O(n^{log₂7}) + * для малых n — O(n³) +* по памяти: + * O(n²) с учётом временных подматриц + +--- + +## 4. Параллельная реализация (MPI) + +### 4.1 Общая схема + +MPI-реализация использует параллелизм верхнего уровня алгоритма Штрассена. +Семь независимых произведений (M₁ … M₇) распределяются между MPI-процессами. +Если количество процессов меньше 7, оставшиеся произведения вычисляются на процессе с рангом 0. + +--- + +### 4.2 Разбиение вычислений + +Для матриц размера n × n: +* матрицы A и B разбиваются на подматрицы A₁₁, A₁₂, A₂₁, A₂₂ и аналогично для B; +* каждому процессу назначается вычисление одного из Mi; +* используется MPI_Comm_split для формирования подкоммуникаторов. + +--- + +### 4.3 Обмен данными + +* локальные результаты Mi сериализуются в одномерный буфер (flatten); +* передаются на процесс 0 с помощью MPI_Send; +* процесс 0 собирает все Mi и формирует итоговую матрицу C; +* результат рассылается всем процессам через MPI_Bcast. + +--- + +### 4.4 Особенности реализации + +* параллелизация выполняется только на верхнем уровне рекурсии; +* дальнейшие рекурсивные вызовы выполняются локально; +* при числе процессов > 7 избыточные процессы не участвуют в вычислениях. + +--- + +### 4.5 Сложность + +* вычислительная сложность — как у SEQ версии; +* ускорение достигается за счёт параллельного вычисления независимых Mi; +* накладные расходы связаны с: + * созданием подкоммуникаторов; + * передачей данных; + * синхронизацией процессов. + +--- + +## 5. Тестирование корректности + +Для проверки корректности был реализован набор функциональных тестов, включающий: +* матрицы размеров от 1×1 до 5×5; +* единичные матрицы; +* нулевые матрицы; +* матрицы с отрицательными элементами; +* дробные значения; +* повторяющиеся элементы; +* матрицы, размер которых не является степенью двойки. + +Всего выполнено 32 функциональных теста, каждый из которых запускался: +* для SEQ версии; +* для MPI версии. + +Все тесты успешно пройдены. + +--- + +## 6. Экспериментальное исследование производительности + +Измерения проводились на матрицах размера 256 × 256. + +| Число процессов (P) |Время SEQ (сек) |Время MPI (сек) | Ускорение (S) | Эффективность (E) | +|---------------------|-----------------|----------------|---------------|-------------------| +| 1 | 0.260 | 0.262 | 0.99 | 0.99 | +| 2 | 0.269 | 0.227 | 1.18 | 0.59 | +| 4 | 0.339 | 0.170 | 1.99 | 0.50 | +| 8 | 0.546 | 0.096 | 5.69 | 0.71 | +| 16 | 1.217 | 0.155 | 7.85 | 0.49 | +| 32 | 2.168 | 0.362 | 5.99 | 0.19 | + +Графики производительности + +![График времени выполнения](data/time_vs_processes.png) +*Рис. 1. Зависимость времени выполнения от числа процессов.* + +![График ускорения](data/speedup.png) +*Рис. 2. Зависимость ускорения от числа процессов.* + +![График эффективности](data/efficiency.png) +*Рис. 3. Зависимость эффективности от числа процессов.* + +--- + +## 7. Анализ результатов + +При 1 процессе ускорение близко к 1, что подтверждает корректность измерений. +Максимальное ускорение достигается при 16 процессах (≈ 7.85), однако эффективность при этом уже снижается. +Наилучшая эффективность наблюдается при 8 процессах (≈ 0.71), что соответствует числу независимых подзадач алгоритма Штрассена. +При дальнейшем увеличении числа процессов эффективность резко падает из-за накладных расходов MPI и недоиспользования процессов. + +--- + +## 8. Выводы + +В ходе работы были реализованы и исследованы последовательная и параллельная версии алгоритма Штрассена для умножения плотных матриц. + +Основные выводы: +* алгоритм Штрассена корректно работает для матриц произвольного размера; +* MPI-реализация демонстрирует значительное ускорение по сравнению с SEQ; +* наилучшая эффективность достигается при количестве процессов, близком к числу независимых подзадач (7); +* при большом числе процессов накладные расходы начинают доминировать. + +Разработанная реализация подтверждает эффективность комбинирования алгоритмической оптимизации (Штрассен) и параллельных вычислений (MPI) для задач линейной алгебры. + +--- + +## 9. Используемые источники + +1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) +2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) +3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) +4. Matrix Multiplication - [https://www.geeksforgeeks.org/dsa/strassens-matrix-multiplication/](https://www.geeksforgeeks.org/dsa/strassens-matrix-multiplication/) +5. Александр Охотин. Математические основы алгоритмов, осень 2025 г. Лекция 5. Структуры данных в алгоритме Дейкстры. Пути между всеми парами вершин в графе: алгоритм Варшалла. Пути между всеми парами вершин в графе с весами: алгоритм Флойда–Варшалла. Достижимость в графе и умножение матриц. Алгоритм Штрассена быстрого умножения матриц - [https://users.math-cs.spbu.ru/~okhotin/teaching/algorithms1_2025/okhotin_algorithms1_2025_l5.pdf](https://users.math-cs.spbu.ru/~okhotin/teaching/algorithms1_2025/okhotin_algorithms1_2025_l5.pdf) + +--- diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index d60224df8d..a7933ab729 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -4,19 +4,15 @@ #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" - namespace goriacheva_k_strassen_algorithm { -GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ( - const InType& in) { +GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; } bool GoriachevaKStrassenAlgorithmSEQ::ValidationImpl() { - return is_square(GetInput().A) && - is_square(GetInput().B) && - GetInput().A.size() == GetInput().B.size(); + return is_square(GetInput().A) && is_square(GetInput().B) && GetInput().A.size() == GetInput().B.size(); } bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { @@ -25,8 +21,8 @@ bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { } bool GoriachevaKStrassenAlgorithmSEQ::RunImpl() { - const auto& A = input_matrices_.A; - const auto& B = input_matrices_.B; + const auto &A = input_matrices_.A; + const auto &B = input_matrices_.B; std::size_t n = A.size(); std::size_t m = next_power_of_two(n); @@ -45,4 +41,4 @@ bool GoriachevaKStrassenAlgorithmSEQ::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp index c8608a0ac6..0fdaf0bf79 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -1,12 +1,12 @@ #include +#include #include #include #include #include #include #include -#include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" @@ -18,19 +18,15 @@ namespace goriacheva_k_strassen_algorithm { using FuncParam = ppc::util::FuncTestParam; -class GoriachevaKStrassenAlgorithmFuncTests - : public ppc::util::BaseRunFuncTests { +class GoriachevaKStrassenAlgorithmFuncTests : public ppc::util::BaseRunFuncTests { public: - static std::string PrintTestParam(const testing::TestParamInfo& info) { - return std::get( - ppc::util::GTestParamIndex::kNameTest)>(info.param); + static std::string PrintTestParam(const testing::TestParamInfo &info) { + return std::get(ppc::util::GTestParamIndex::kNameTest)>(info.param); } protected: void SetUp() override { - const auto& params = - std::get( - ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + const auto ¶ms = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); input_ = std::get<0>(params); expected_ = std::get<1>(params); } @@ -39,11 +35,15 @@ class GoriachevaKStrassenAlgorithmFuncTests return input_; } - bool CheckTestOutputData(OutType& output_data) final { - if (output_data.size() != expected_.size()) return false; + bool CheckTestOutputData(OutType &output_data) final { + if (output_data.size() != expected_.size()) { + return false; + } for (std::size_t i = 0; i < expected_.size(); ++i) { - if (output_data[i].size() != expected_[i].size()) return false; + if (output_data[i].size() != expected_[i].size()) { + return false; + } for (std::size_t j = 0; j < expected_[i].size(); ++j) { if (std::fabs(output_data[i][j] - expected_[i][j]) > 1e-6) { return false; @@ -61,9 +61,7 @@ class GoriachevaKStrassenAlgorithmFuncTests namespace { std::vector LoadTestParams() { - const std::string path = - ppc::util::GetAbsoluteTaskPath( - PPC_ID_goriacheva_k_strassen_algorithm, "tests.json"); + const std::string path = ppc::util::GetAbsoluteTaskPath(PPC_ID_goriacheva_k_strassen_algorithm, "tests.json"); std::ifstream fin(path); if (!fin.is_open()) { @@ -76,42 +74,28 @@ std::vector LoadTestParams() { std::vector cases; cases.reserve(j.size() * 2); - const std::string settings_path = - PPC_SETTINGS_goriacheva_k_strassen_algorithm; + const std::string settings_path = PPC_SETTINGS_goriacheva_k_strassen_algorithm; const std::string mpi_suffix = - ppc::task::GetStringTaskType( - GoriachevaKStrassenAlgorithmMPI::GetStaticTypeOfTask(), - settings_path); + ppc::task::GetStringTaskType(GoriachevaKStrassenAlgorithmMPI::GetStaticTypeOfTask(), settings_path); const std::string seq_suffix = - ppc::task::GetStringTaskType( - GoriachevaKStrassenAlgorithmSEQ::GetStaticTypeOfTask(), - settings_path); + ppc::task::GetStringTaskType(GoriachevaKStrassenAlgorithmSEQ::GetStaticTypeOfTask(), settings_path); - for (const auto& item : j) { + for (const auto &item : j) { InType input; input.A = item.at("input").at("A").get>>(); input.B = item.at("input").at("B").get>>(); - OutType expected = - item.at("result").get(); + OutType expected = item.at("result").get(); - TestType tc{ - input, - expected, - item.at("name").get() - }; + TestType tc{input, expected, item.at("name").get()}; std::string mpi_name = std::get<2>(tc) + "_" + mpi_suffix; - cases.emplace_back( - ppc::task::TaskGetter, - mpi_name, tc); + cases.emplace_back(ppc::task::TaskGetter, mpi_name, tc); std::string seq_name = std::get<2>(tc) + "_" + seq_suffix; - cases.emplace_back( - ppc::task::TaskGetter, - seq_name, tc); + cases.emplace_back(ppc::task::TaskGetter, seq_name, tc); } return cases; @@ -123,11 +107,8 @@ TEST_P(GoriachevaKStrassenAlgorithmFuncTests, MatrixMultiplication) { ExecuteTest(GetParam()); } -INSTANTIATE_TEST_SUITE_P( - GoriachevaKStrassenAlgorithmFunctionalTests, - GoriachevaKStrassenAlgorithmFuncTests, - testing::ValuesIn(kFuncParams), - GoriachevaKStrassenAlgorithmFuncTests::PrintTestParam); +INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmFunctionalTests, GoriachevaKStrassenAlgorithmFuncTests, + testing::ValuesIn(kFuncParams), GoriachevaKStrassenAlgorithmFuncTests::PrintTestParam); } // namespace -} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index d7964fc99a..e920ff4e3f 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -11,8 +11,7 @@ namespace goriacheva_k_strassen_algorithm { -class GoriachevaKStrassenAlgorithmPerfTests - : public ppc::util::BaseRunPerfTests { +class GoriachevaKStrassenAlgorithmPerfTests : public ppc::util::BaseRunPerfTests { public: static constexpr std::size_t kMatrixSize = 256; @@ -26,7 +25,7 @@ class GoriachevaKStrassenAlgorithmPerfTests return input_; } - bool CheckTestOutputData(OutType& /*output_data*/) final { + bool CheckTestOutputData(OutType & /*output_data*/) final { return true; // perf-тесты не проверяют корректность } @@ -42,10 +41,7 @@ namespace { auto BuildPerfParams() { const auto all_tasks = - ppc::util::MakeAllPerfTasks< - InType, - GoriachevaKStrassenAlgorithmMPI, - GoriachevaKStrassenAlgorithmSEQ>( + ppc::util::MakeAllPerfTasks( PPC_SETTINGS_goriacheva_k_strassen_algorithm); return ppc::util::TupleToGTestValues(all_tasks); @@ -53,17 +49,12 @@ auto BuildPerfParams() { const auto kPerfParams = BuildPerfParams(); -std::string MakePerfName( - const ::testing::TestParamInfo< - GoriachevaKStrassenAlgorithmPerfTests::ParamType>& info) { +std::string MakePerfName(const ::testing::TestParamInfo &info) { return GoriachevaKStrassenAlgorithmPerfTests::CustomPerfTestName(info); } -INSTANTIATE_TEST_SUITE_P( - GoriachevaKStrassenAlgorithmPerfomanceTests, - GoriachevaKStrassenAlgorithmPerfTests, - kPerfParams, - MakePerfName); +INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmPerfomanceTests, GoriachevaKStrassenAlgorithmPerfTests, + kPerfParams, MakePerfName); } // namespace -} // namespace goriacheva_k_strassen_algorithm \ No newline at end of file +} // namespace goriacheva_k_strassen_algorithm From 1e294bc2fbbdac21c95c79d69153eb3baa8c0ec4 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 19:12:13 +0300 Subject: [PATCH 09/21] Fix third task --- .../common/include/common.hpp | 142 +++++++++--------- .../mpi/include/ops_mpi.hpp | 8 +- .../mpi/src/ops_mpi.cpp | 130 ++++++++-------- .../goriacheva_k_strassen_algorithm/report.md | 6 +- .../seq/include/ops_seq.hpp | 6 +- .../seq/src/ops_seq.cpp | 26 ++-- .../tests/functional/main.cpp | 14 +- .../tests/performance/main.cpp | 16 +- 8 files changed, 178 insertions(+), 170 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index a2d63104ef..86fb9d1ccd 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -7,44 +7,44 @@ #include "task/include/task.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { using Matrix = std::vector>; struct InType { - Matrix A; - Matrix B; + Matrix a; + Matrix b; }; using OutType = Matrix; using TestType = std::tuple; using BaseTask = ppc::task::Task; -inline std::vector flatten(const Matrix &M) { +inline std::vector Flatten(const Matrix &m) { std::vector buf; - buf.reserve(M.size() * M.size()); - for (const auto &row : M) { + buf.reserve(m.size() * m.size()); + for (const auto &row : m) { buf.insert(buf.end(), row.begin(), row.end()); } return buf; } -inline Matrix unflatten(const std::vector &buf, std::size_t n) { - Matrix M(n, std::vector(n)); +inline Matrix UnFlatten(const std::vector &buf, std::size_t n) { + Matrix m(n, std::vector(n)); for (std::size_t i = 0; i < n; ++i) { for (std::size_t j = 0; j < n; ++j) { - M[i][j] = buf[i * n + j]; + m[i][j] = buf[(i * n) + j]; } } - return M; + return m; } -inline bool is_square(const Matrix &M) { - if (M.empty()) { +inline bool IsSquare(const Matrix &m) { + if (m.empty()) { return false; } - std::size_t n = M.size(); - for (const auto &r : M) { + std::size_t n = m.size(); + for (const auto &r : m) { if (r.size() != n) { return false; } @@ -52,7 +52,7 @@ inline bool is_square(const Matrix &M) { return true; } -inline std::size_t next_power_of_two(std::size_t n) { +inline std::size_t NextPowerOfTwo(std::size_t n) { std::size_t p = 1; while (p < n) { p <<= 1; @@ -60,106 +60,110 @@ inline std::size_t next_power_of_two(std::size_t n) { return p; } -inline Matrix pad_matrix(const Matrix &A, std::size_t new_size) { - Matrix R(new_size, std::vector(new_size, 0.0)); - for (std::size_t i = 0; i < A.size(); ++i) { - for (std::size_t j = 0; j < A.size(); ++j) { - R[i][j] = A[i][j]; +inline Matrix PadMatrix(const Matrix &a, std::size_t new_size) { + Matrix r(new_size, std::vector(new_size, 0.0)); + for (std::size_t i = 0; i < a.size(); ++i) { + for (std::size_t j = 0; j < a.size(); ++j) { + r[i][j] = a[i][j]; } } - return R; + return r; } -inline Matrix crop_matrix(const Matrix &A, std::size_t size) { - Matrix R(size, std::vector(size)); +inline Matrix CropMatrix(const Matrix &a, std::size_t size) { + Matrix r(size, std::vector(size)); for (std::size_t i = 0; i < size; ++i) { for (std::size_t j = 0; j < size; ++j) { - R[i][j] = A[i][j]; + r[i][j] = a[i][j]; } } - return R; + return r; } -inline Matrix add(const Matrix &A, const Matrix &B) { - std::size_t n = A.size(); - Matrix C(n, std::vector(n)); +inline Matrix Add(const Matrix &a, const Matrix &b) { + std::size_t n = a.size(); + Matrix c(n, std::vector(n)); for (std::size_t i = 0; i < n; ++i) { for (std::size_t j = 0; j < n; ++j) { - C[i][j] = A[i][j] + B[i][j]; + c[i][j] = a[i][j] + b[i][j]; } } - return C; + return c; } -inline Matrix sub(const Matrix &A, const Matrix &B) { - std::size_t n = A.size(); - Matrix C(n, std::vector(n)); +inline Matrix Sub(const Matrix &a, const Matrix &b) { + std::size_t n = a.size(); + Matrix c(n, std::vector(n)); for (std::size_t i = 0; i < n; ++i) { for (std::size_t j = 0; j < n; ++j) { - C[i][j] = A[i][j] - B[i][j]; + c[i][j] = a[i][j] - b[i][j]; } } - return C; + return c; } -inline Matrix naive_multiply(const Matrix &A, const Matrix &B) { - std::size_t n = A.size(); - Matrix C(n, std::vector(n, 0.0)); +inline Matrix NaiveMultiply(const Matrix &a, const Matrix &b) { + std::size_t n = a.size(); + Matrix c(n, std::vector(n, 0.0)); for (std::size_t i = 0; i < n; ++i) { for (std::size_t k = 0; k < n; ++k) { for (std::size_t j = 0; j < n; ++j) { - C[i][j] += A[i][k] * B[k][j]; + c[i][j] += a[i][k] * b[k][j]; } } } - return C; + return c; } -inline Matrix strassen(const Matrix &A, const Matrix &B, std::size_t threshold = 128) { - std::size_t n = A.size(); +inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) { + std::size_t n = a.size(); if (n <= threshold) { - return naive_multiply(A, B); + return NaiveMultiply(a, b); } std::size_t k = n / 2; - Matrix A11(k, std::vector(k)), A12(k, std::vector(k)); - Matrix A21(k, std::vector(k)), A22(k, std::vector(k)); - Matrix B11(k, std::vector(k)), B12(k, std::vector(k)); - Matrix B21(k, std::vector(k)), B22(k, std::vector(k)); + Matrix a11(k, std::vector(k)); + Matrix a12(k, std::vector(k)); + Matrix a21(k, std::vector(k)); + Matrix a22(k, std::vector(k)); + Matrix b11(k, std::vector(k)); + Matrix b12(k, std::vector(k)); + Matrix b21(k, std::vector(k)); + Matrix b22(k, std::vector(k)); for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { - A11[i][j] = A[i][j]; - A12[i][j] = A[i][j + k]; - A21[i][j] = A[i + k][j]; - A22[i][j] = A[i + k][j + k]; - B11[i][j] = B[i][j]; - B12[i][j] = B[i][j + k]; - B21[i][j] = B[i + k][j]; - B22[i][j] = B[i + k][j + k]; + a11[i][j] = a[i][j]; + a12[i][j] = a[i][j + k]; + a21[i][j] = a[i + k][j]; + a22[i][j] = a[i + k][j + k]; + b11[i][j] = b[i][j]; + b12[i][j] = b[i][j + k]; + b21[i][j] = b[i + k][j]; + b22[i][j] = b[i + k][j + k]; } } - Matrix M1 = strassen(add(A11, A22), add(B11, B22), threshold); - Matrix M2 = strassen(add(A21, A22), B11, threshold); - Matrix M3 = strassen(A11, sub(B12, B22), threshold); - Matrix M4 = strassen(A22, sub(B21, B11), threshold); - Matrix M5 = strassen(add(A11, A12), B22, threshold); - Matrix M6 = strassen(sub(A21, A11), add(B11, B12), threshold); - Matrix M7 = strassen(sub(A12, A22), add(B21, B22), threshold); + Matrix m1 = Strassen(Add(a11, a22), Add(b11, b22), threshold); + Matrix m2 = Strassen(Add(a21, a22), b11, threshold); + Matrix m3 = Strassen(a11, Sub(b12, b22), threshold); + Matrix m4 = Strassen(a22, Sub(b21, b11), threshold); + Matrix m5 = Strassen(Add(a11, a12), b22, threshold); + Matrix m6 = Strassen(Sub(a21, a11), Add(b11, b12), threshold); + Matrix m7 = Strassen(Sub(a12, a22), Add(b21, b22), threshold); - Matrix C(n, std::vector(n)); + Matrix c(n, std::vector(n)); for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { - C[i][j] = M1[i][j] + M4[i][j] - M5[i][j] + M7[i][j]; - C[i][j + k] = M3[i][j] + M5[i][j]; - C[i + k][j] = M2[i][j] + M4[i][j]; - C[i + k][j + k] = M1[i][j] - M2[i][j] + M3[i][j] + M6[i][j]; + c[i][j] = m1[i][j] + m4[i][j] - m5[i][j] + m7[i][j]; + c[i][j + k] = m3[i][j] + m5[i][j]; + c[i + k][j] = m2[i][j] + m4[i][j]; + c[i + k][j + k] = m1[i][j] - m2[i][j] + m3[i][j] + m6[i][j]; } } - return C; + return c; } -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp index 984302782d..c2a2a71e0e 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -4,10 +4,10 @@ #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { class GoriachevaKStrassenAlgorithmMPI : public BaseTask { public: @@ -26,7 +26,7 @@ class GoriachevaKStrassenAlgorithmMPI : public BaseTask { InType input_matrices_; OutType result_matrix_; - Matrix mpi_strassen_top(const Matrix &A, const Matrix &B); + Matrix mpi_Strassen_top(const Matrix &A, const Matrix &B); }; -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index 9b3a353f01..ffc13c57cc 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -1,13 +1,13 @@ -#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" #include #include #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); @@ -15,7 +15,7 @@ GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &i } bool GoriachevaKStrassenAlgorithmMPI::ValidationImpl() { - return is_square(GetInput().A) && is_square(GetInput().B) && GetInput().A.size() == GetInput().B.size(); + return IsSquare(GetInput().a) && IsSquare(GetInput().b) && GetInput().a.size() == GetInput().b.size(); } bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { @@ -23,80 +23,84 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { return true; } -Matrix GoriachevaKStrassenAlgorithmMPI::mpi_strassen_top(const Matrix &A, const Matrix &B) { +Matrix GoriachevaKStrassenAlgorithmMPI::mpi_Strassen_top(const Matrix &a, const Matrix &b) { int rank = 0; int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - std::size_t n = A.size(); + std::size_t n = a.size(); if (size == 1 || n <= 1) { - return strassen(A, B); + return Strassen(a, b); } std::size_t k = n / 2; - Matrix A11(k, std::vector(k)), A12(k, std::vector(k)); - Matrix A21(k, std::vector(k)), A22(k, std::vector(k)); - Matrix B11(k, std::vector(k)), B12(k, std::vector(k)); - Matrix B21(k, std::vector(k)), B22(k, std::vector(k)); + Matrix a11(k, std::vector(k)); + Matrix a12(k, std::vector(k)); + Matrix a21(k, std::vector(k)); + Matrix a22(k, std::vector(k)); + Matrix b11(k, std::vector(k)); + Matrix b12(k, std::vector(k)); + Matrix b21(k, std::vector(k)); + Matrix b22(k, std::vector(k)); for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { - A11[i][j] = A[i][j]; - A12[i][j] = A[i][j + k]; - A21[i][j] = A[i + k][j]; - A22[i][j] = A[i + k][j + k]; - B11[i][j] = B[i][j]; - B12[i][j] = B[i][j + k]; - B21[i][j] = B[i + k][j]; - B22[i][j] = B[i + k][j + k]; + a11[i][j] = a[i][j]; + a12[i][j] = a[i][j + k]; + a21[i][j] = a[i + k][j]; + a22[i][j] = a[i + k][j + k]; + b11[i][j] = b[i][j]; + b12[i][j] = b[i][j + k]; + b21[i][j] = b[i + k][j]; + b22[i][j] = b[i + k][j + k]; } } int num_tasks = std::min(7, size); int task_id = rank % num_tasks; - MPI_Comm subcomm; - MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &subcomm); + MPI_Comm Subcomm; + MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &Subcomm); - int sub_rank; - MPI_Comm_rank(subcomm, &sub_rank); + int Sub_rank; + MPI_Comm_rank(Subcomm, &Sub_rank); - Matrix Mi; - if (sub_rank == 0) { + Matrix mi; + if (Sub_rank == 0) { switch (task_id) { case 0: - Mi = strassen(add(A11, A22), add(B11, B22)); + mi = Strassen(Add(a11, a22), Add(b11, b22)); break; case 1: - Mi = strassen(add(A21, A22), B11); + mi = Strassen(Add(a21, a22), b11); break; case 2: - Mi = strassen(A11, sub(B12, B22)); + mi = Strassen(a11, Sub(b12, b22)); break; case 3: - Mi = strassen(A22, sub(B21, B11)); + mi = Strassen(a22, Sub(b21, b11)); break; case 4: - Mi = strassen(add(A11, A12), B22); + mi = Strassen(Add(a11, a12), b22); break; case 5: - Mi = strassen(sub(A21, A11), add(B11, B12)); + mi = Strassen(Sub(a21, a11), Add(b11, b12)); break; case 6: - Mi = strassen(sub(A12, A22), add(B21, B22)); + mi = Strassen(Sub(a12, a22), Add(b21, b22)); break; } } - MPI_Comm_free(&subcomm); + MPI_Comm_free(&Subcomm); - std::vector M(7); + std::vector m(7); if (rank == 0) { - if (task_id < num_tasks && sub_rank == 0) { - M[task_id] = Mi; + if (task_id < num_tasks && Sub_rank == 0) { + m[task_id] = mi; } for (int i = 1; i < num_tasks; ++i) { @@ -107,74 +111,74 @@ Matrix GoriachevaKStrassenAlgorithmMPI::mpi_strassen_top(const Matrix &A, const MPI_Recv(&tid, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status); MPI_Recv(buf.data(), k * k, MPI_DOUBLE, status.MPI_SOURCE, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - M[tid] = unflatten(buf, k); + m[tid] = UnFlatten(buf, k); } for (int t = num_tasks; t < 7; ++t) { switch (t) { case 0: - M[0] = strassen(add(A11, A22), add(B11, B22)); + m[0] = Strassen(Add(a11, a22), Add(b11, b22)); break; case 1: - M[1] = strassen(add(A21, A22), B11); + m[1] = Strassen(Add(a21, a22), b11); break; case 2: - M[2] = strassen(A11, sub(B12, B22)); + m[2] = Strassen(a11, Sub(b12, b22)); break; case 3: - M[3] = strassen(A22, sub(B21, B11)); + m[3] = Strassen(a22, Sub(b21, b11)); break; case 4: - M[4] = strassen(add(A11, A12), B22); + m[4] = Strassen(Add(a11, a12), b22); break; case 5: - M[5] = strassen(sub(A21, A11), add(B11, B12)); + m[5] = Strassen(Sub(a21, a11), Add(b11, b12)); break; case 6: - M[6] = strassen(sub(A12, A22), add(B21, B22)); + m[6] = Strassen(Sub(a12, a22), Add(b21, b22)); break; } } - } else if (sub_rank == 0) { - auto buf = flatten(Mi); + } else if (Sub_rank == 0) { + auto buf = Flatten(mi); MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); MPI_Send(buf.data(), k * k, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); } - Matrix C(n, std::vector(n)); + Matrix c(n, std::vector(n)); if (rank == 0) { for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { - C[i][j] = M[0][i][j] + M[3][i][j] - M[4][i][j] + M[6][i][j]; - C[i][j + k] = M[2][i][j] + M[4][i][j]; - C[i + k][j] = M[1][i][j] + M[3][i][j]; - C[i + k][j + k] = M[0][i][j] - M[1][i][j] + M[2][i][j] + M[5][i][j]; + c[i][j] = m[0][i][j] + m[3][i][j] - m[4][i][j] + m[6][i][j]; + c[i][j + k] = m[2][i][j] + m[4][i][j]; + c[i + k][j] = m[1][i][j] + m[3][i][j]; + c[i + k][j + k] = m[0][i][j] - m[1][i][j] + m[2][i][j] + m[5][i][j]; } } } - auto flatC = flatten(C); + auto flatC = Flatten(c); MPI_Bcast(flatC.data(), n * n, MPI_DOUBLE, 0, MPI_COMM_WORLD); if (rank != 0) { - C = unflatten(flatC, n); + c = UnFlatten(flatC, n); } - return C; + return c; } bool GoriachevaKStrassenAlgorithmMPI::RunImpl() { - const auto &A = input_matrices_.A; - const auto &B = input_matrices_.B; + const auto &a = input_matrices_.a; + const auto &b = input_matrices_.b; - std::size_t n = A.size(); - std::size_t m = next_power_of_two(n); + std::size_t n = a.size(); + std::size_t m = NextPowerOfTwo(n); - Matrix A_pad = (n == m) ? A : pad_matrix(A, m); - Matrix B_pad = (n == m) ? B : pad_matrix(B, m); + Matrix a_pad = (n == m) ? a : PadMatrix(a, m); + Matrix b_pad = (n == m) ? b : PadMatrix(b, m); - Matrix C_pad = mpi_strassen_top(A_pad, B_pad); - result_matrix_ = (n == m) ? C_pad : crop_matrix(C_pad, n); + Matrix c_pad = mpi_Strassen_top(a_pad, b_pad); + result_matrix_ = (n == m) ? c_pad : CropMatrix(c_pad, n); return true; } @@ -184,4 +188,4 @@ bool GoriachevaKStrassenAlgorithmMPI::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/report.md b/tasks/goriacheva_k_strassen_algorithm/report.md index 6e25be7166..49a0c79143 100644 --- a/tasks/goriacheva_k_strassen_algorithm/report.md +++ b/tasks/goriacheva_k_strassen_algorithm/report.md @@ -47,7 +47,7 @@ O(n³), что делает его неэффективным для матри Алгоритм Штрассена требует, чтобы размер матрицы был степенью двойки. Если это не так, матрицы дополняются нулями до ближайшей степени двойки: -m = next_power_of_two(n) +m = NextPowerOfTwo(n) После вычислений результат обрезается до исходного размера. --- @@ -93,7 +93,7 @@ MPI-реализация использует параллелизм верхн ### 4.3 Обмен данными -* локальные результаты Mi сериализуются в одномерный буфер (flatten); +* локальные результаты Mi сериализуются в одномерный буфер (Flatten); * передаются на процесс 0 с помощью MPI_Send; * процесс 0 собирает все Mi и формирует итоговую матрицу C; * результат рассылается всем процессам через MPI_Bcast. @@ -192,7 +192,7 @@ MPI-реализация использует параллелизм верхн 1. Parallel Programming Course - [https://learning-process.github.io/parallel_programming_course/ru/](https://learning-process.github.io/parallel_programming_course/ru/) 2. Parallel Programming 2025-2026 Video-Records - [https://disk.yandex.ru/d/NvHFyhOJCQU65w](https://disk.yandex.ru/d/NvHFyhOJCQU65w) 3. Open MPI: Documentation — [https://www.open-mpi.org/doc/](https://www.open-mpi.org/doc/) -4. Matrix Multiplication - [https://www.geeksforgeeks.org/dsa/strassens-matrix-multiplication/](https://www.geeksforgeeks.org/dsa/strassens-matrix-multiplication/) +4. Matrix Multiplication - [https://www.geeksforgeeks.org/dsa/Strassens-matrix-multiplication/](https://www.geeksforgeeks.org/dsa/Strassens-matrix-multiplication/) 5. Александр Охотин. Математические основы алгоритмов, осень 2025 г. Лекция 5. Структуры данных в алгоритме Дейкстры. Пути между всеми парами вершин в графе: алгоритм Варшалла. Пути между всеми парами вершин в графе с весами: алгоритм Флойда–Варшалла. Достижимость в графе и умножение матриц. Алгоритм Штрассена быстрого умножения матриц - [https://users.math-cs.spbu.ru/~okhotin/teaching/algorithms1_2025/okhotin_algorithms1_2025_l5.pdf](https://users.math-cs.spbu.ru/~okhotin/teaching/algorithms1_2025/okhotin_algorithms1_2025_l5.pdf) --- diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp index a4ed41e6de..b3900f70ce 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp @@ -2,10 +2,10 @@ #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { class GoriachevaKStrassenAlgorithmSEQ : public BaseTask { public: @@ -24,4 +24,4 @@ class GoriachevaKStrassenAlgorithmSEQ : public BaseTask { OutType result_matrix_; }; -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index a7933ab729..714398b198 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -1,10 +1,10 @@ -#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); @@ -12,7 +12,7 @@ GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ(const InType &i } bool GoriachevaKStrassenAlgorithmSEQ::ValidationImpl() { - return is_square(GetInput().A) && is_square(GetInput().B) && GetInput().A.size() == GetInput().B.size(); + return IsSquare(GetInput().a) && IsSquare(GetInput().b) && GetInput().a.size() == GetInput().a.size(); } bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { @@ -21,17 +21,17 @@ bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { } bool GoriachevaKStrassenAlgorithmSEQ::RunImpl() { - const auto &A = input_matrices_.A; - const auto &B = input_matrices_.B; + const auto &a = input_matrices_.a; + const auto &b = input_matrices_.b; - std::size_t n = A.size(); - std::size_t m = next_power_of_two(n); + std::size_t n = a.size(); + std::size_t m = NextPowerOfTwo(n); - Matrix A_pad = (n == m) ? A : pad_matrix(A, m); - Matrix B_pad = (n == m) ? B : pad_matrix(B, m); + Matrix a_pad = (n == m) ? a : PadMatrix(a, m); + Matrix b_pad = (n == m) ? b : PadMatrix(b, m); - Matrix C_pad = strassen(A_pad, B_pad); - result_matrix_ = (n == m) ? C_pad : crop_matrix(C_pad, n); + Matrix c_pad = Strassen(a_pad, b_pad); + result_matrix_ = (n == m) ? c_pad : CropMatrix(c_pad, n); return true; } @@ -41,4 +41,4 @@ bool GoriachevaKStrassenAlgorithmSEQ::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp index 0fdaf0bf79..7589e2dbd5 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -8,13 +8,13 @@ #include #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" -#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" #include "task/include/task.hpp" #include "util/include/func_test_util.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { using FuncParam = ppc::util::FuncTestParam; @@ -84,8 +84,8 @@ std::vector LoadTestParams() { for (const auto &item : j) { InType input; - input.A = item.at("input").at("A").get>>(); - input.B = item.at("input").at("B").get>>(); + input.a = item.at("input").at("A").get>>(); + input.b = item.at("input").at("B").get>>(); OutType expected = item.at("result").get(); @@ -111,4 +111,4 @@ INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmFunctionalTests, Goriacheva testing::ValuesIn(kFuncParams), GoriachevaKStrassenAlgorithmFuncTests::PrintTestParam); } // namespace -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index e920ff4e3f..0704ca1645 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -4,12 +4,12 @@ #include #include -#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" -#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" -namespace goriacheva_k_strassen_algorithm { +namespace goriacheva_k_Strassen_algorithm { class GoriachevaKStrassenAlgorithmPerfTests : public ppc::util::BaseRunPerfTests { public: @@ -17,8 +17,8 @@ class GoriachevaKStrassenAlgorithmPerfTests : public ppc::util::BaseRunPerfTests protected: void SetUp() override { - input_.A.assign(kMatrixSize, std::vector(kMatrixSize, 1.0)); - input_.B.assign(kMatrixSize, std::vector(kMatrixSize, 2.0)); + input_.a.assign(kMatrixSize, std::vector(kMatrixSize, 1.0)); + input_.b.assign(kMatrixSize, std::vector(kMatrixSize, 2.0)); } InType GetTestInputData() final { @@ -26,7 +26,7 @@ class GoriachevaKStrassenAlgorithmPerfTests : public ppc::util::BaseRunPerfTests } bool CheckTestOutputData(OutType & /*output_data*/) final { - return true; // perf-тесты не проверяют корректность + return true; } private: @@ -57,4 +57,4 @@ INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmPerfomanceTests, Goriacheva kPerfParams, MakePerfName); } // namespace -} // namespace goriacheva_k_strassen_algorithm +} // namespace goriacheva_k_Strassen_algorithm From f0e007249e56371054e7fae52b9918945b240e20 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 19:21:34 +0300 Subject: [PATCH 10/21] Fix2 third task --- .../goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp | 2 +- tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp | 2 +- .../goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp | 2 +- tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp | 4 ++-- .../tests/functional/main.cpp | 6 +++--- .../tests/performance/main.cpp | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp index c2a2a71e0e..2d07a21975 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -4,7 +4,7 @@ #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" namespace goriacheva_k_Strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index ffc13c57cc..f0679dc87f 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -5,7 +5,7 @@ #include #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" namespace goriacheva_k_Strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp index b3900f70ce..34bf252d24 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp @@ -2,7 +2,7 @@ #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" namespace goriacheva_k_Strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index 714398b198..35c9ad123a 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -1,8 +1,8 @@ -#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" namespace goriacheva_k_Strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp index 7589e2dbd5..63785520cf 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -8,9 +8,9 @@ #include #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" -#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "task/include/task.hpp" #include "util/include/func_test_util.hpp" diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index 0704ca1645..c31d8d9c91 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -4,9 +4,9 @@ #include #include -#include "goriacheva_k_Strassen_algorithm/common/include/common.hpp" -#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" -#include "goriacheva_k_Strassen_algorithm/seq/include/ops_seq.hpp" +#include "goriacheva_k_strassen_algorithm/common/include/common.hpp" +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" namespace goriacheva_k_Strassen_algorithm { From 87bccdd6b071fa4e89249ba35d3f9d0e9c465d51 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 19:29:54 +0300 Subject: [PATCH 11/21] Fix3 third task --- tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index f0679dc87f..e6b465616e 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -1,4 +1,4 @@ -#include "goriacheva_k_Strassen_algorithm/mpi/include/ops_mpi.hpp" +#include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" #include From 2ad8bd93db4adc5bb0c9d5a8a157301b86d4c060 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 20:37:22 +0300 Subject: [PATCH 12/21] Fix4 third task --- .../common/include/common.hpp | 8 ++++---- .../mpi/include/ops_mpi.hpp | 6 +++--- .../goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp | 9 ++++----- .../seq/include/ops_seq.hpp | 4 ++-- .../goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp | 6 ++---- .../tests/functional/main.cpp | 4 ++-- .../tests/performance/main.cpp | 5 ++--- 7 files changed, 19 insertions(+), 23 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 86fb9d1ccd..3712a20bad 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -7,13 +7,13 @@ #include "task/include/task.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { using Matrix = std::vector>; struct InType { - Matrix a; - Matrix b; + Matrix a{}; + Matrix b{}; }; using OutType = Matrix; @@ -166,4 +166,4 @@ inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = return c; } -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp index 2d07a21975..53980f32e4 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -7,7 +7,7 @@ #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { class GoriachevaKStrassenAlgorithmMPI : public BaseTask { public: @@ -26,7 +26,7 @@ class GoriachevaKStrassenAlgorithmMPI : public BaseTask { InType input_matrices_; OutType result_matrix_; - Matrix mpi_Strassen_top(const Matrix &A, const Matrix &B); + Matrix MpiStrassenTop(const Matrix &a, const Matrix &b); }; -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index e6b465616e..6edb620f7d 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -2,12 +2,11 @@ #include -#include #include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); @@ -23,7 +22,7 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { return true; } -Matrix GoriachevaKStrassenAlgorithmMPI::mpi_Strassen_top(const Matrix &a, const Matrix &b) { +Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Matrix &b) { int rank = 0; int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); @@ -177,7 +176,7 @@ bool GoriachevaKStrassenAlgorithmMPI::RunImpl() { Matrix a_pad = (n == m) ? a : PadMatrix(a, m); Matrix b_pad = (n == m) ? b : PadMatrix(b, m); - Matrix c_pad = mpi_Strassen_top(a_pad, b_pad); + Matrix c_pad = MpiStrassenTop(a_pad, b_pad); result_matrix_ = (n == m) ? c_pad : CropMatrix(c_pad, n); return true; @@ -188,4 +187,4 @@ bool GoriachevaKStrassenAlgorithmMPI::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp index 34bf252d24..a4ed41e6de 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp @@ -5,7 +5,7 @@ #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { class GoriachevaKStrassenAlgorithmSEQ : public BaseTask { public: @@ -24,4 +24,4 @@ class GoriachevaKStrassenAlgorithmSEQ : public BaseTask { OutType result_matrix_; }; -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index 35c9ad123a..e41c700293 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -1,10 +1,8 @@ #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" -#include - #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); @@ -41,4 +39,4 @@ bool GoriachevaKStrassenAlgorithmSEQ::PostProcessingImpl() { return true; } -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp index 63785520cf..6fd54165b1 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -14,7 +14,7 @@ #include "task/include/task.hpp" #include "util/include/func_test_util.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { using FuncParam = ppc::util::FuncTestParam; @@ -111,4 +111,4 @@ INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmFunctionalTests, Goriacheva testing::ValuesIn(kFuncParams), GoriachevaKStrassenAlgorithmFuncTests::PrintTestParam); } // namespace -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index c31d8d9c91..ff66517766 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" @@ -9,7 +8,7 @@ #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" -namespace goriacheva_k_Strassen_algorithm { +namespace goriacheva_k_strassen_algorithm { class GoriachevaKStrassenAlgorithmPerfTests : public ppc::util::BaseRunPerfTests { public: @@ -57,4 +56,4 @@ INSTANTIATE_TEST_SUITE_P(GoriachevaKStrassenAlgorithmPerfomanceTests, Goriacheva kPerfParams, MakePerfName); } // namespace -} // namespace goriacheva_k_Strassen_algorithm +} // namespace goriacheva_k_strassen_algorithm From 734882eff7b181f3f25e054af8efc8f349320d4d Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 21:47:57 +0300 Subject: [PATCH 13/21] Fix5 third task --- .../common/include/common.hpp | 8 +++-- .../mpi/include/ops_mpi.hpp | 4 --- .../mpi/src/ops_mpi.cpp | 32 +++++++++++-------- .../seq/include/ops_seq.hpp | 2 -- .../seq/src/ops_seq.cpp | 2 ++ .../tests/performance/main.cpp | 1 + 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 3712a20bad..3e80b6d184 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -12,8 +12,8 @@ namespace goriacheva_k_strassen_algorithm { using Matrix = std::vector>; struct InType { - Matrix a{}; - Matrix b{}; + Matrix a; + Matrix b; }; using OutType = Matrix; @@ -44,12 +44,14 @@ inline bool IsSquare(const Matrix &m) { return false; } std::size_t n = m.size(); + // NOLINT(readability-use-anyofallof) for (const auto &r : m) { if (r.size() != n) { return false; } } return true; + // NOLINT(readability-use-anyofallof) } inline std::size_t NextPowerOfTwo(std::size_t n) { @@ -115,6 +117,7 @@ inline Matrix NaiveMultiply(const Matrix &a, const Matrix &b) { return c; } +// NOLINTBEGIN(misc-no-recursion) inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) { std::size_t n = a.size(); if (n <= threshold) { @@ -165,5 +168,6 @@ inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = return c; } +// NOLINTBEGIN(misc-no-recursion) } // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp index 53980f32e4..b4aad228b1 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -1,9 +1,5 @@ #pragma once -#include - -#include - #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index 6edb620f7d..849c61ef5e 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -2,6 +2,7 @@ #include +#include #include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" @@ -22,14 +23,16 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { return true; } -Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Matrix &b) { +Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( + const Matrix &a, const Matrix &b) // NOLINT(readability-function-cognitive-complexity) +{ int rank = 0; int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); std::size_t n = a.size(); - if (size == 1 || n <= 1) { + if ((size == 1) || (n <= 1)) { return Strassen(a, b); } @@ -60,14 +63,14 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma int num_tasks = std::min(7, size); int task_id = rank % num_tasks; - MPI_Comm Subcomm; + MPI_Comm Subcomm = MPI_COMM_NULL; MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &Subcomm); - int Sub_rank; - MPI_Comm_rank(Subcomm, &Sub_rank); + int sub_rank = 0; + MPI_Comm_rank(Subcomm, &sub_rank); Matrix mi; - if (Sub_rank == 0) { + if (sub_rank == 0) { switch (task_id) { case 0: mi = Strassen(Add(a11, a22), Add(b11, b22)); @@ -98,7 +101,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma std::vector m(7); if (rank == 0) { - if (task_id < num_tasks && Sub_rank == 0) { + if (task_id < num_tasks && sub_rank == 0) { m[task_id] = mi; } @@ -108,13 +111,16 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma MPI_Status status; MPI_Recv(&tid, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status); - MPI_Recv(buf.data(), k * k, MPI_DOUBLE, status.MPI_SOURCE, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + MPI_Recv(buf.data(), static_cast(k * k), MPI_DOUBLE, status.MPI_SOURCE, 1, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); m[tid] = UnFlatten(buf, k); } - for (int t = num_tasks; t < 7; ++t) { - switch (t) { + for (int task = num_tasks; task < 7; ++task) { + switch (task) { + default: + break; case 0: m[0] = Strassen(Add(a11, a22), Add(b11, b22)); break; @@ -138,10 +144,10 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma break; } } - } else if (Sub_rank == 0) { + } else if (sub_rank == 0) { auto buf = Flatten(mi); MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); - MPI_Send(buf.data(), k * k, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); + MPI_Send(buf.data(), static_cast(k * k), MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); } Matrix c(n, std::vector(n)); @@ -157,7 +163,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma } auto flatC = Flatten(c); - MPI_Bcast(flatC.data(), n * n, MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Bcast(flatC.data(), static_cast(n * n), MPI_DOUBLE, 0, MPI_COMM_WORLD); if (rank != 0) { c = UnFlatten(flatC, n); diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp index a4ed41e6de..94a68d2958 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" #include "task/include/task.hpp" diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index e41c700293..b8db3018ee 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -1,5 +1,7 @@ #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" +#include + #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" namespace goriacheva_k_strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index ff66517766..4938843b1e 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include "goriacheva_k_strassen_algorithm/common/include/common.hpp" From 87d94bed55c9f8d6038e0a4d7ea19b4d892733c3 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 23:19:36 +0300 Subject: [PATCH 14/21] Fix6 third task --- .../common/include/common.hpp | 18 ++++++---------- .../mpi/include/ops_mpi.hpp | 2 +- .../mpi/src/ops_mpi.cpp | 21 ++++++++++--------- .../seq/src/ops_seq.cpp | 2 +- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 3e80b6d184..71109f8124 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include #include #include @@ -43,15 +45,8 @@ inline bool IsSquare(const Matrix &m) { if (m.empty()) { return false; } - std::size_t n = m.size(); - // NOLINT(readability-use-anyofallof) - for (const auto &r : m) { - if (r.size() != n) { - return false; - } - } - return true; - // NOLINT(readability-use-anyofallof) + const std::size_t n = m.size(); + return std::ranges::all_of(m, [n](const auto &r) { return r.size() == n; }); } inline std::size_t NextPowerOfTwo(std::size_t n) { @@ -117,8 +112,8 @@ inline Matrix NaiveMultiply(const Matrix &a, const Matrix &b) { return c; } -// NOLINTBEGIN(misc-no-recursion) -inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) { +inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) // NOLINTBEGIN(misc-no-recursion) +{ std::size_t n = a.size(); if (n <= threshold) { return NaiveMultiply(a, b); @@ -168,6 +163,5 @@ inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = return c; } -// NOLINTBEGIN(misc-no-recursion) } // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp index b4aad228b1..4d6595016d 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp @@ -22,7 +22,7 @@ class GoriachevaKStrassenAlgorithmMPI : public BaseTask { InType input_matrices_; OutType result_matrix_; - Matrix MpiStrassenTop(const Matrix &a, const Matrix &b); + static Matrix MpiStrassenTop(const Matrix &a, const Matrix &b); }; } // namespace goriacheva_k_strassen_algorithm diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index 849c61ef5e..c78756cbec 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -63,11 +64,11 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( int num_tasks = std::min(7, size); int task_id = rank % num_tasks; - MPI_Comm Subcomm = MPI_COMM_NULL; - MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &Subcomm); + MPI_Comm subcomm = MPI_COMM_NULL; + MPI_Comm_split(MPI_COMM_WORLD, task_id, rank, &subcomm); int sub_rank = 0; - MPI_Comm_rank(Subcomm, &sub_rank); + MPI_Comm_rank(subcomm, &sub_rank); Matrix mi; if (sub_rank == 0) { @@ -96,7 +97,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( } } - MPI_Comm_free(&Subcomm); + MPI_Comm_free(&subcomm); std::vector m(7); @@ -106,7 +107,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( } for (int i = 1; i < num_tasks; ++i) { - int tid; + int tid = 0; std::vector buf(k * k); MPI_Status status; @@ -119,8 +120,6 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( for (int task = num_tasks; task < 7; ++task) { switch (task) { - default: - break; case 0: m[0] = Strassen(Add(a11, a22), Add(b11, b22)); break; @@ -142,6 +141,8 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( case 6: m[6] = Strassen(Sub(a12, a22), Add(b21, b22)); break; + default: + break; } } } else if (sub_rank == 0) { @@ -162,11 +163,11 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( } } - auto flatC = Flatten(c); - MPI_Bcast(flatC.data(), static_cast(n * n), MPI_DOUBLE, 0, MPI_COMM_WORLD); + auto flat_c = Flatten(c); + MPI_Bcast(flat_c.data(), static_cast(n * n), MPI_DOUBLE, 0, MPI_COMM_WORLD); if (rank != 0) { - c = UnFlatten(flatC, n); + c = UnFlatten(flat_c, n); } return c; diff --git a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp index b8db3018ee..f9fee144f0 100644 --- a/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/seq/src/ops_seq.cpp @@ -12,7 +12,7 @@ GoriachevaKStrassenAlgorithmSEQ::GoriachevaKStrassenAlgorithmSEQ(const InType &i } bool GoriachevaKStrassenAlgorithmSEQ::ValidationImpl() { - return IsSquare(GetInput().a) && IsSquare(GetInput().b) && GetInput().a.size() == GetInput().a.size(); + return IsSquare(GetInput().a) && IsSquare(GetInput().b) && GetInput().a.size() == GetInput().b.size(); } bool GoriachevaKStrassenAlgorithmSEQ::PreProcessingImpl() { From 2094284a2562c922e21a3c37c448411c60d16027 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 23:31:17 +0300 Subject: [PATCH 15/21] Fix7 third task --- tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp | 1 + tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp index 6fd54165b1..d8fe06d2fa 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/functional/main.cpp @@ -13,6 +13,7 @@ #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "task/include/task.hpp" #include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" namespace goriacheva_k_strassen_algorithm { diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index 4938843b1e..bb194884cf 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -8,6 +8,7 @@ #include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" +#include "util/include/util.hpp" namespace goriacheva_k_strassen_algorithm { From 2b51e756cd38f46adb65faa034613f709f2274f3 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 23:41:59 +0300 Subject: [PATCH 16/21] Fix8 third task --- tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 71109f8124..62ea928de6 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -112,7 +112,7 @@ inline Matrix NaiveMultiply(const Matrix &a, const Matrix &b) { return c; } -inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) // NOLINTBEGIN(misc-no-recursion) +inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) // NOLINT(misc-no-recursion) { std::size_t n = a.size(); if (n <= threshold) { From ef4b018d4d3742d2e30b2815b2e51eadc4cbe05c Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sat, 3 Jan 2026 23:58:54 +0300 Subject: [PATCH 17/21] Fix9 third task --- .../data/tests.json | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/data/tests.json b/tasks/goriacheva_k_strassen_algorithm/data/tests.json index 9efb7c60b9..f290a4c054 100644 --- a/tasks/goriacheva_k_strassen_algorithm/data/tests.json +++ b/tasks/goriacheva_k_strassen_algorithm/data/tests.json @@ -14,5 +14,59 @@ { "name": "4x4_negatives", "input": { "A": [[-1.0,2.0,-3.0,4.0],[5.0,-6.0,7.0,-8.0],[-9.0,10.0,-11.0,12.0],[13.0,-14.0,15.0,-16.0]], "B": [[16.0,-15.0,14.0,-13.0],[-12.0,11.0,-10.0,9.0],[8.0,-7.0,6.0,-5.0],[-4.0,3.0,-2.0,1.0]] }, "result": [[-80.0,70.0,-60.0,50.0],[240.0,-214.0,188.0,-162.0],[-400.0,358.0,-316.0,274.0],[560.0,-502.0,444.0,-386.0]] }, { "name": "4x4_repeats", "input": { "A": [[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0]], "B": [[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0]] }, "result": [[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0]] }, { "name": "4x4_fractional", "input": { "A": [[1.5, 2.0, 3.0, 4.5],[5.5, 6.5, 7.0, 8.0],[9.0, 10.5, 11.5, 12.0],[13.0, 14.5, 15.0, 16.5]], "B": [[0.5, 1.0, 1.5, 2.0],[2.5, 3.0, 3.5, 4.0],[4.5, 5.0, 5.5, 6.0],[6.5, 7.0, 7.5, 8.0]] }, "result": [[48.5, 54.0, 59.5, 65.0],[102.5, 116.0, 129.5, 143.0],[160.5, 182.0, 203.5, 225.0],[217.5, 247.0, 276.5, 306.0]] }, - { "name": "5x5_identity", "input": { "A": [[1.0,0.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0,0.0],[0.0,0.0,1.0,0.0,0.0],[0.0,0.0,0.0,1.0,0.0],[0.0,0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] }, "result": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] } + { "name": "5x5_identity", "input": { "A": [[1.0,0.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0,0.0],[0.0,0.0,1.0,0.0,0.0],[0.0,0.0,0.0,1.0,0.0],[0.0,0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] }, "result": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] }, +{ + "name": "6x6_identity", + "input": { + "A": [[1,0,0,0,0,0], + [0,1,0,0,0,0], + [0,0,1,0,0,0], + [0,0,0,1,0,0], + [0,0,0,0,1,0], + [0,0,0,0,0,1]], + "B": [[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]] + }, + "result": [[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]] +}, +{ + "name": "8x8_mixed", + "input": { + "A": [[1,2,3,4,5,6,7,8], + [8,7,6,5,4,3,2,1], + [1,3,5,7,9,11,13,15], + [2,4,6,8,10,12,14,16], + [1,1,1,1,1,1,1,1], + [2,2,2,2,2,2,2,2], + [3,3,3,3,3,3,3,3], + [4,4,4,4,4,4,4,4]], + "B": [[1,0,0,0,0,0,0,0], + [0,1,0,0,0,0,0,0], + [0,0,1,0,0,0,0,0], + [0,0,0,1,0,0,0,0], + [0,0,0,0,1,0,0,0], + [0,0,0,0,0,1,0,0], + [0,0,0,0,0,0,1,0], + [0,0,0,0,0,0,0,1]] + }, + "result": [[1,2,3,4,5,6,7,8], + [8,7,6,5,4,3,2,1], + [1,3,5,7,9,11,13,15], + [2,4,6,8,10,12,14,16], + [1,1,1,1,1,1,1,1], + [2,2,2,2,2,2,2,2], + [3,3,3,3,3,3,3,3], + [4,4,4,4,4,4,4,4]] +} + + ] From ef81a6ccfeefe7b1034e12eaefc2fe9ac30c11e7 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sun, 4 Jan 2026 01:27:00 +0300 Subject: [PATCH 18/21] Fix9 third task --- tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp | 1 - tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp | 2 ++ tasks/goriacheva_k_strassen_algorithm/report.md | 2 +- .../goriacheva_k_strassen_algorithm/tests/performance/main.cpp | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp index 62ea928de6..3b8c1cd7ff 100644 --- a/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp +++ b/tasks/goriacheva_k_strassen_algorithm/common/include/common.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index c78756cbec..e7bad49464 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -94,6 +94,8 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( case 6: mi = Strassen(Sub(a12, a22), Add(b21, b22)); break; + default: + break; } } diff --git a/tasks/goriacheva_k_strassen_algorithm/report.md b/tasks/goriacheva_k_strassen_algorithm/report.md index 49a0c79143..0a0b94ef50 100644 --- a/tasks/goriacheva_k_strassen_algorithm/report.md +++ b/tasks/goriacheva_k_strassen_algorithm/report.md @@ -130,7 +130,7 @@ MPI-реализация использует параллелизм верхн * повторяющиеся элементы; * матрицы, размер которых не является степенью двойки. -Всего выполнено 32 функциональных теста, каждый из которых запускался: +Всего выполнено 36 функциональных теста, каждый из которых запускался: * для SEQ версии; * для MPI версии. diff --git a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp index bb194884cf..4938843b1e 100644 --- a/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/tests/performance/main.cpp @@ -8,7 +8,6 @@ #include "goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp" #include "goriacheva_k_strassen_algorithm/seq/include/ops_seq.hpp" #include "util/include/perf_test_util.hpp" -#include "util/include/util.hpp" namespace goriacheva_k_strassen_algorithm { From ea72780d2446ac592f0ce2bde5002e1bcd2099eb Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sun, 4 Jan 2026 07:57:32 +0300 Subject: [PATCH 19/21] Fix9 third task --- .../mpi/src/ops_mpi.cpp | 173 +++++++++--------- 1 file changed, 83 insertions(+), 90 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index e7bad49464..d8cbc53fbb 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -10,6 +10,76 @@ namespace goriacheva_k_strassen_algorithm { +struct Blocks { + Matrix a11, a12, a21, a22; + Matrix b11, b12, b21, b22; +}; + +Blocks SplitMatrices(const Matrix &a, const Matrix &b, std::size_t k) { + Blocks blk{Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), + Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), + Matrix(k, std::vector(k)), Matrix(k, std::vector(k))}; + + for (std::size_t i = 0; i < k; ++i) { + for (std::size_t j = 0; j < k; ++j) { + blk.a11[i][j] = a[i][j]; + blk.a12[i][j] = a[i][j + k]; + blk.a21[i][j] = a[i + k][j]; + blk.a22[i][j] = a[i + k][j + k]; + + blk.b11[i][j] = b[i][j]; + blk.b12[i][j] = b[i][j + k]; + blk.b21[i][j] = b[i + k][j]; + blk.b22[i][j] = b[i + k][j + k]; + } + } + + return blk; +} + +Matrix ComputeMi(int task_id, const Blocks &blk) { + switch (task_id) { + case 0: + return Strassen(Add(blk.a11, blk.a22), Add(blk.b11, blk.b22)); + case 1: + return Strassen(Add(blk.a21, blk.a22), blk.b11); + case 2: + return Strassen(blk.a11, Sub(blk.b12, blk.b22)); + case 3: + return Strassen(blk.a22, Sub(blk.b21, blk.b11)); + case 4: + return Strassen(Add(blk.a11, blk.a12), blk.b22); + case 5: + return Strassen(Sub(blk.a21, blk.a11), Add(blk.b11, blk.b12)); + case 6: + return Strassen(Sub(blk.a12, blk.a22), Add(blk.b21, blk.b22)); + default: + return {}; + } +} + +void ComputeMissingTasks(std::vector &m, int start_task, const Blocks &blk) { + for (int task = start_task; task < 7; ++task) { + m[task] = ComputeMi(task, blk); + } +} + +Matrix AssembleResult(const std::vector &m, std::size_t k) { + std::size_t n = 2 * k; + Matrix c(n, std::vector(n)); + + for (std::size_t i = 0; i < k; ++i) { + for (std::size_t j = 0; j < k; ++j) { + c[i][j] = m[0][i][j] + m[3][i][j] - m[4][i][j] + m[6][i][j]; + c[i][j + k] = m[2][i][j] + m[4][i][j]; + c[i + k][j] = m[1][i][j] + m[3][i][j]; + c[i + k][j + k] = m[0][i][j] - m[1][i][j] + m[2][i][j] + m[5][i][j]; + } + } + + return c; +} + GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; @@ -24,42 +94,18 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { return true; } -Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( - const Matrix &a, const Matrix &b) // NOLINT(readability-function-cognitive-complexity) -{ - int rank = 0; - int size = 1; +Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Matrix &b) { + int rank = 0, size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); std::size_t n = a.size(); - if ((size == 1) || (n <= 1)) { + if (size == 1 || n <= 1) { return Strassen(a, b); } std::size_t k = n / 2; - - Matrix a11(k, std::vector(k)); - Matrix a12(k, std::vector(k)); - Matrix a21(k, std::vector(k)); - Matrix a22(k, std::vector(k)); - Matrix b11(k, std::vector(k)); - Matrix b12(k, std::vector(k)); - Matrix b21(k, std::vector(k)); - Matrix b22(k, std::vector(k)); - - for (std::size_t i = 0; i < k; ++i) { - for (std::size_t j = 0; j < k; ++j) { - a11[i][j] = a[i][j]; - a12[i][j] = a[i][j + k]; - a21[i][j] = a[i + k][j]; - a22[i][j] = a[i + k][j + k]; - b11[i][j] = b[i][j]; - b12[i][j] = b[i][j + k]; - b21[i][j] = b[i + k][j]; - b22[i][j] = b[i + k][j + k]; - } - } + auto blocks = SplitMatrices(a, b, k); int num_tasks = std::min(7, size); int task_id = rank % num_tasks; @@ -72,31 +118,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( Matrix mi; if (sub_rank == 0) { - switch (task_id) { - case 0: - mi = Strassen(Add(a11, a22), Add(b11, b22)); - break; - case 1: - mi = Strassen(Add(a21, a22), b11); - break; - case 2: - mi = Strassen(a11, Sub(b12, b22)); - break; - case 3: - mi = Strassen(a22, Sub(b21, b11)); - break; - case 4: - mi = Strassen(Add(a11, a12), b22); - break; - case 5: - mi = Strassen(Sub(a21, a11), Add(b11, b12)); - break; - case 6: - mi = Strassen(Sub(a12, a22), Add(b21, b22)); - break; - default: - break; - } + mi = ComputeMi(task_id, blocks); } MPI_Comm_free(&subcomm); @@ -120,52 +142,23 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop( m[tid] = UnFlatten(buf, k); } - for (int task = num_tasks; task < 7; ++task) { - switch (task) { - case 0: - m[0] = Strassen(Add(a11, a22), Add(b11, b22)); - break; - case 1: - m[1] = Strassen(Add(a21, a22), b11); - break; - case 2: - m[2] = Strassen(a11, Sub(b12, b22)); - break; - case 3: - m[3] = Strassen(a22, Sub(b21, b11)); - break; - case 4: - m[4] = Strassen(Add(a11, a12), b22); - break; - case 5: - m[5] = Strassen(Sub(a21, a11), Add(b11, b12)); - break; - case 6: - m[6] = Strassen(Sub(a12, a22), Add(b21, b22)); - break; - default: - break; - } - } + ComputeMissingTasks(m, num_tasks, blocks); } else if (sub_rank == 0) { auto buf = Flatten(mi); MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); MPI_Send(buf.data(), static_cast(k * k), MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); } - Matrix c(n, std::vector(n)); + Matrix c; + std::vector flat_c; + if (rank == 0) { - for (std::size_t i = 0; i < k; ++i) { - for (std::size_t j = 0; j < k; ++j) { - c[i][j] = m[0][i][j] + m[3][i][j] - m[4][i][j] + m[6][i][j]; - c[i][j + k] = m[2][i][j] + m[4][i][j]; - c[i + k][j] = m[1][i][j] + m[3][i][j]; - c[i + k][j + k] = m[0][i][j] - m[1][i][j] + m[2][i][j] + m[5][i][j]; - } - } + c = AssembleResult(m, k); + flat_c = Flatten(c); + } else { + flat_c.resize(n * n); } - auto flat_c = Flatten(c); MPI_Bcast(flat_c.data(), static_cast(n * n), MPI_DOUBLE, 0, MPI_COMM_WORLD); if (rank != 0) { From b41cf428ba448835fd2ddd75c9c8f3ebc7b05179 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sun, 4 Jan 2026 08:58:26 +0300 Subject: [PATCH 20/21] Fix9 third task --- .../mpi/src/ops_mpi.cpp | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index d8cbc53fbb..f6b00859e8 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -10,15 +10,28 @@ namespace goriacheva_k_strassen_algorithm { +namespace { + struct Blocks { - Matrix a11, a12, a21, a22; - Matrix b11, b12, b21, b22; + Matrix a11; + Matrix a12; + Matrix a21; + Matrix a22; + Matrix b11; + Matrix b12; + Matrix b21; + Matrix b22; }; -Blocks SplitMatrices(const Matrix &a, const Matrix &b, std::size_t k) { - Blocks blk{Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), - Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), Matrix(k, std::vector(k)), - Matrix(k, std::vector(k)), Matrix(k, std::vector(k))}; +Blocks split_matrices(const Matrix &a, const Matrix &b, std::size_t k) { + Blocks blk{.a11 = Matrix(k, std::vector(k)), + .a12 = Matrix(k, std::vector(k)), + .a21 = Matrix(k, std::vector(k)), + .a22 = Matrix(k, std::vector(k)), + .b11 = Matrix(k, std::vector(k)), + .b12 = Matrix(k, std::vector(k)), + .b21 = Matrix(k, std::vector(k)), + .b22 = Matrix(k, std::vector(k))}; for (std::size_t i = 0; i < k; ++i) { for (std::size_t j = 0; j < k; ++j) { @@ -37,7 +50,7 @@ Blocks SplitMatrices(const Matrix &a, const Matrix &b, std::size_t k) { return blk; } -Matrix ComputeMi(int task_id, const Blocks &blk) { +Matrix compute_mi(int task_id, const Blocks &blk) { switch (task_id) { case 0: return Strassen(Add(blk.a11, blk.a22), Add(blk.b11, blk.b22)); @@ -58,13 +71,13 @@ Matrix ComputeMi(int task_id, const Blocks &blk) { } } -void ComputeMissingTasks(std::vector &m, int start_task, const Blocks &blk) { +void compute_missing_tasks(std::vector &m, int start_task, const Blocks &blk) { for (int task = start_task; task < 7; ++task) { - m[task] = ComputeMi(task, blk); + m[task] = compute_mi(task, blk); } } -Matrix AssembleResult(const std::vector &m, std::size_t k) { +Matrix assemble_result(const std::vector &m, std::size_t k) { std::size_t n = 2 * k; Matrix c(n, std::vector(n)); @@ -80,6 +93,8 @@ Matrix AssembleResult(const std::vector &m, std::size_t k) { return c; } +} // namespace + GoriachevaKStrassenAlgorithmMPI::GoriachevaKStrassenAlgorithmMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; @@ -95,7 +110,8 @@ bool GoriachevaKStrassenAlgorithmMPI::PreProcessingImpl() { } Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Matrix &b) { - int rank = 0, size = 1; + int rank = 0; + int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); @@ -105,7 +121,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma } std::size_t k = n / 2; - auto blocks = SplitMatrices(a, b, k); + auto blocks = split_matrices(a, b, k); int num_tasks = std::min(7, size); int task_id = rank % num_tasks; @@ -118,7 +134,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma Matrix mi; if (sub_rank == 0) { - mi = ComputeMi(task_id, blocks); + mi = compute_mi(task_id, blocks); } MPI_Comm_free(&subcomm); @@ -142,7 +158,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma m[tid] = UnFlatten(buf, k); } - ComputeMissingTasks(m, num_tasks, blocks); + compute_missing_tasks(m, num_tasks, blocks); } else if (sub_rank == 0) { auto buf = Flatten(mi); MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); @@ -153,7 +169,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma std::vector flat_c; if (rank == 0) { - c = AssembleResult(m, k); + c = assemble_result(m, k); flat_c = Flatten(c); } else { flat_c.resize(n * n); From 22f351b517aac4fef7871a2f553c4caab58bc575 Mon Sep 17 00:00:00 2001 From: GoriachevaKsenia Date: Sun, 4 Jan 2026 10:09:11 +0300 Subject: [PATCH 21/21] Fix9 third task --- .../mpi/src/ops_mpi.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp index f6b00859e8..33719e9b34 100644 --- a/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp +++ b/tasks/goriacheva_k_strassen_algorithm/mpi/src/ops_mpi.cpp @@ -23,7 +23,7 @@ struct Blocks { Matrix b22; }; -Blocks split_matrices(const Matrix &a, const Matrix &b, std::size_t k) { +Blocks SplitMatrices(const Matrix &a, const Matrix &b, std::size_t k) { Blocks blk{.a11 = Matrix(k, std::vector(k)), .a12 = Matrix(k, std::vector(k)), .a21 = Matrix(k, std::vector(k)), @@ -50,7 +50,7 @@ Blocks split_matrices(const Matrix &a, const Matrix &b, std::size_t k) { return blk; } -Matrix compute_mi(int task_id, const Blocks &blk) { +Matrix ComputeMi(int task_id, const Blocks &blk) { switch (task_id) { case 0: return Strassen(Add(blk.a11, blk.a22), Add(blk.b11, blk.b22)); @@ -71,13 +71,13 @@ Matrix compute_mi(int task_id, const Blocks &blk) { } } -void compute_missing_tasks(std::vector &m, int start_task, const Blocks &blk) { +void ComputeMissingTasks(std::vector &m, int start_task, const Blocks &blk) { for (int task = start_task; task < 7; ++task) { - m[task] = compute_mi(task, blk); + m[task] = ComputeMi(task, blk); } } -Matrix assemble_result(const std::vector &m, std::size_t k) { +Matrix AssembleResult(const std::vector &m, std::size_t k) { std::size_t n = 2 * k; Matrix c(n, std::vector(n)); @@ -121,7 +121,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma } std::size_t k = n / 2; - auto blocks = split_matrices(a, b, k); + auto blocks = SplitMatrices(a, b, k); int num_tasks = std::min(7, size); int task_id = rank % num_tasks; @@ -134,7 +134,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma Matrix mi; if (sub_rank == 0) { - mi = compute_mi(task_id, blocks); + mi = ComputeMi(task_id, blocks); } MPI_Comm_free(&subcomm); @@ -158,7 +158,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma m[tid] = UnFlatten(buf, k); } - compute_missing_tasks(m, num_tasks, blocks); + ComputeMissingTasks(m, num_tasks, blocks); } else if (sub_rank == 0) { auto buf = Flatten(mi); MPI_Send(&task_id, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); @@ -169,7 +169,7 @@ Matrix GoriachevaKStrassenAlgorithmMPI::MpiStrassenTop(const Matrix &a, const Ma std::vector flat_c; if (rank == 0) { - c = assemble_result(m, k); + c = AssembleResult(m, k); flat_c = Flatten(c); } else { flat_c.resize(n * n);