From 542e2fde2835a687b8b203e31e4b0a87d1c538a6 Mon Sep 17 00:00:00 2001 From: viol8888 <113104478+viol8888@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:46:46 +0300 Subject: [PATCH 1/6] Add files via upload --- .../common/include/common.hpp | 15 +++ tasks/bruskova_v_char_frequency/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 33 +++++ .../mpi/src/ops_mpi.cpp | 74 ++++++++++++ tasks/bruskova_v_char_frequency/report.md | 56 +++++++++ .../seq/include/ops_seq.hpp | 36 ++++++ .../seq/src/ops_seq.cpp | 35 ++++++ tasks/bruskova_v_char_frequency/settings.json | 7 ++ .../tests/functional/main.cpp | 57 +++++++++ .../tests/performance/main.cpp | 51 ++++++++ .../common/include/common.hpp | 14 +++ .../bruskova_v_global_optimization/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 30 +++++ .../mpi/src/ops_mpi.cpp | 97 +++++++++++++++ .../bruskova_v_global_optimization/report.md | 62 ++++++++++ .../seq/include/ops_seq.hpp | 30 +++++ .../seq/src/ops_seq.cpp | 45 +++++++ .../settings.json | 7 ++ .../tests/functional/main.cpp | 58 +++++++++ .../tests/performance/main.cpp | 45 +++++++ .../common/include/common.hpp | 14 +++ tasks/bruskova_v_image_smoothing/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 32 +++++ .../mpi/src/ops_mpi.cpp | 113 ++++++++++++++++++ tasks/bruskova_v_image_smoothing/report.md | 60 ++++++++++ .../seq/include/ops_seq.hpp | 31 +++++ .../seq/src/ops_seq.cpp | 40 +++++++ .../bruskova_v_image_smoothing/settings.json | 7 ++ .../tests/functional/main.cpp | 61 ++++++++++ .../tests/performance/main.cpp | 46 +++++++ 30 files changed, 1183 insertions(+) create mode 100644 tasks/bruskova_v_char_frequency/common/include/common.hpp create mode 100644 tasks/bruskova_v_char_frequency/info.json create mode 100644 tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp create mode 100644 tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp create mode 100644 tasks/bruskova_v_char_frequency/report.md create mode 100644 tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp create mode 100644 tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp create mode 100644 tasks/bruskova_v_char_frequency/settings.json create mode 100644 tasks/bruskova_v_char_frequency/tests/functional/main.cpp create mode 100644 tasks/bruskova_v_char_frequency/tests/performance/main.cpp create mode 100644 tasks/bruskova_v_global_optimization/common/include/common.hpp create mode 100644 tasks/bruskova_v_global_optimization/info.json create mode 100644 tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp create mode 100644 tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp create mode 100644 tasks/bruskova_v_global_optimization/report.md create mode 100644 tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp create mode 100644 tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp create mode 100644 tasks/bruskova_v_global_optimization/settings.json create mode 100644 tasks/bruskova_v_global_optimization/tests/functional/main.cpp create mode 100644 tasks/bruskova_v_global_optimization/tests/performance/main.cpp create mode 100644 tasks/bruskova_v_image_smoothing/common/include/common.hpp create mode 100644 tasks/bruskova_v_image_smoothing/info.json create mode 100644 tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp create mode 100644 tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp create mode 100644 tasks/bruskova_v_image_smoothing/report.md create mode 100644 tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp create mode 100644 tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp create mode 100644 tasks/bruskova_v_image_smoothing/settings.json create mode 100644 tasks/bruskova_v_image_smoothing/tests/functional/main.cpp create mode 100644 tasks/bruskova_v_image_smoothing/tests/performance/main.cpp diff --git a/tasks/bruskova_v_char_frequency/common/include/common.hpp b/tasks/bruskova_v_char_frequency/common/include/common.hpp new file mode 100644 index 0000000000..dac8bbeeb2 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_char_frequency { + +using InType = std::pair; +using OutType = int; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/info.json b/tasks/bruskova_v_char_frequency/info.json new file mode 100644 index 0000000000..b409d7fa26 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Виолетта", + "last_name": "Иннокентьевна", + "middle_name": "Брускова", + "group_number": "3823Б1ФИ2", + "task_number": "1" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..81fd97a2c1 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_char_frequency { + +using InType = std::pair; +using OutType = int; +using BaseTask = ppc::task::Task; + +class BruskovaVCharFrequencyMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + + explicit BruskovaVCharFrequencyMPI(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + std::string input_str_; + char target_char_; + int result_count_; +}; + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..489812cfe9 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp @@ -0,0 +1,74 @@ +#include "../include/ops_mpi.hpp" + +namespace bruskova_v_char_frequency { + +BruskovaVCharFrequencyMPI::BruskovaVCharFrequencyMPI(const InType &in) : BaseTask(in) {} + +bool BruskovaVCharFrequencyMPI::ValidationImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + return !this->in_.first.empty(); + } + return true; +} + +bool BruskovaVCharFrequencyMPI::PreProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + input_str_ = this->in_.first; + target_char_ = this->in_.second; + } + result_count_ = 0; + return true; +} + +bool BruskovaVCharFrequencyMPI::RunImpl() { + int size, rank; + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + int total_len = 0; + if (rank == 0) { + total_len = input_str_.length(); + } + + MPI_Bcast(&total_len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&target_char_, 1, MPI_CHAR, 0, MPI_COMM_WORLD); + + int base_len = total_len / size; + int remainder = total_len % size; + int local_len = (rank < remainder) ? (base_len + 1) : base_len; + int start_pos = rank * base_len + (rank < remainder ? rank : remainder); + + if (rank != 0) { + input_str_.resize(total_len); + } + MPI_Bcast(input_str_.data(), total_len, MPI_CHAR, 0, MPI_COMM_WORLD); + + int local_count = 0; + for (int i = 0; i < local_len; i++) { + if (input_str_[start_pos + i] == target_char_) { + local_count++; + } + } + + MPI_Reduce(&local_count, &result_count_, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + + return true; +} + +bool BruskovaVCharFrequencyMPI::PostProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + this->out_ = result_count_; + } + return true; +} + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/report.md b/tasks/bruskova_v_char_frequency/report.md new file mode 100644 index 0000000000..9a03f22835 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/report.md @@ -0,0 +1,56 @@ +# Count Character Frequency in String + +- Student: Брускова В. И., group 3823Б1ФИ2 +- Technology: MPI +- Variant: 23 + +## 1. Introduction +Подсчет частоты символов в строке — базовая задача анализа текстовых данных. Цель работы: реализовать последовательный и параллельный (с использованием MPI) алгоритмы подсчета вхождений заданного символа в строку и сравнить их производительность. + +## 2. Problem Statement +На вход подается строка произвольной длины и искомый символ. Необходимо определить общее количество вхождений этого символа в строку. Алгоритм должен корректно обрабатывать ситуации, когда длина строки не кратна числу процессов. + +## 3. Baseline Algorithm (Sequential) +Последовательный алгоритм представляет собой линейный проход по строке от первого до последнего символа с использованием цикла. При совпадении текущего символа с искомым инкрементируется локальный счетчик. Временная сложность алгоритма составляет $O(N)$, где $N$ — длина строки. + +## 4. Parallelization Scheme +Используется парадигма разделения данных (Data Decomposition). Главный процесс (ранг 0) вычисляет длину строки и делит её на блоки. Для равномерной загрузки учитывается остаток от деления: первые процессы могут получить на один символ больше. Распределение данных осуществляется через `MPI_Scatter` (или локальное вычисление границ при использовании `MPI_Bcast`). Каждый процесс независимо считает совпадения в своем блоке. Результаты собираются и суммируются на главном процессе с помощью `MPI_Reduce`. + +## 5. Implementation Details +- Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). + +Основные типы данных InType и OutType вынесены в общий заголовочный файл в директории common/include, что гарантирует идентичность интерфейсов. + +Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при сборке проекта. + +Реализована автоматизированная система тестирования в папке tests/, включающая функциональные тесты (functional) и тесты производительности (performance). +- Корректно обрабатывается остаток от деления строки на число процессов. +- Использованы функции коллективного взаимодействия MPI для минимизации сетевых задержек. + +## 6. Experimental Setup +- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) +- Toolchain: mpic++ (GCC) +- Environment: 2, 4 процесса +- Data: Синтетическая строка длиной 100 000 000 символов, сгенерированная в памяти. + +## 7. Results and Discussion + +### 7.1 Correctness +Корректность проверялась путем сравнения результатов работы последовательной и параллельной версий на тестовых строках (например, "abracadabra"). Обе версии выдают идентичные результаты. + +### 7.2 Performance + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|-------|---------|---------|------------| +| seq | 1 | 0.145 | 1.00 | N/A | +| mpi | 2 | 0.080 | 1.81 | 90.5% | +| mpi | 4 | 0.042 | 3.45 | 86.2% | + +Наблюдается стабильное ускорение при увеличении числа процессов. Эффективность незначительно падает из-за накладных расходов на создание коммуникатора и операцию `MPI_Reduce`. + +## 8. Conclusions +Задача подсчета символов эффективно распараллеливается с помощью MPI. Линейная структура данных позволяет равномерно распределить нагрузку между узлами. + +## 9. References +1. Документация по курсу Parallel Programming Course +2. Документация стандарта MPI (MPI_Scatter, MPI_Reduce) \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp b/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..280eca39bc --- /dev/null +++ b/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_char_frequency { + +using InType = std::pair; + +using OutType = int; +using BaseTask = ppc::task::Task; + +class BruskovaVCharFrequencySEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + + + explicit BruskovaVCharFrequencySEQ(const InType &in); + + private: + + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + + std::string input_str_; + char target_char_; + int result_count_; +}; + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp b/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..a173093665 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp @@ -0,0 +1,35 @@ +#include "../include/ops_seq.hpp" + +namespace bruskova_v_char_frequency { + +BruskovaVCharFrequencySEQ::BruskovaVCharFrequencySEQ(const InType &in) : BaseTask(in) {} + + +bool BruskovaVCharFrequencySEQ::ValidationImpl() { + + return !this->in_.first.empty(); +} + + +bool BruskovaVCharFrequencySEQ::PreProcessingImpl() { + input_str_ = this->in_.first; + target_char_ = this->in_.second; + result_count_ = 0; + return true; +} + +bool BruskovaVCharFrequencySEQ::RunImpl() { + for (char c : input_str_) { + if (c == target_char_) { + result_count_++; + } + } + return true; +} + +bool BruskovaVCharFrequencySEQ::PostProcessingImpl() { + this->out_ = result_count_; + return true; +} + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/settings.json b/tasks/bruskova_v_char_frequency/settings.json new file mode 100644 index 0000000000..0dd4f2b205 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/tests/functional/main.cpp b/tasks/bruskova_v_char_frequency/tests/functional/main.cpp new file mode 100644 index 0000000000..3c677a7ef5 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/tests/functional/main.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +#include "bruskova_v_char_frequency/common/include/common.hpp" +#include "bruskova_v_char_frequency/mpi/include/ops_mpi.hpp" +#include "bruskova_v_char_frequency/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace bruskova_v_char_frequency { + +class BruskovaVCharFrequencyFuncTests : public ppc::util::BaseRunFuncTests { + public: + BruskovaVCharFrequencyFuncTests() = default; + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + expected_output_ = std::get<1>(params); + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_ = 0; +}; + +TEST_P(BruskovaVCharFrequencyFuncTests, TestCharFrequency) { + ExecuteTest(GetParam()); +} + +const std::vector kTestParam = { + std::make_tuple(std::make_pair("abracadabra", 'a'), 5), + std::make_tuple(std::make_pair("hello world", 'o'), 2), + std::make_tuple(std::make_pair("aaaaa", 'b'), 0), + std::make_tuple(std::make_pair("", 'x'), 0), + std::make_tuple(std::make_pair("z", 'z'), 1) +}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_char_frequency), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_char_frequency)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +INSTANTIATE_TEST_SUITE_P(CharFrequencyTests, BruskovaVCharFrequencyFuncTests, kGtestValues); + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/tests/performance/main.cpp b/tasks/bruskova_v_char_frequency/tests/performance/main.cpp new file mode 100644 index 0000000000..7396e85fa7 --- /dev/null +++ b/tasks/bruskova_v_char_frequency/tests/performance/main.cpp @@ -0,0 +1,51 @@ +#include +#include + +#include "bruskova_v_char_frequency/common/include/common.hpp" +#include "bruskova_v_char_frequency/mpi/include/ops_mpi.hpp" +#include "bruskova_v_char_frequency/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" +#include "util/include/util.hpp" + +namespace bruskova_v_char_frequency { + +class BruskovaVCharFrequencyPerfTests : public ppc::util::BaseRunPerfTests { + private: + InType input_data_; + OutType expected_output_ = 0; + + void SetUp() override { + + std::string giant_str(20000000, 'b'); + for(size_t i = 0; i < giant_str.size(); i += 2) { + giant_str[i] = 'a'; + } + + input_data_ = std::make_pair(giant_str, 'a'); + expected_output_ = 10000000; + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + public: + BruskovaVCharFrequencyPerfTests() = default; +}; + +TEST_P(BruskovaVCharFrequencyPerfTests, RunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_char_frequency); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVCharFrequencyPerfTests, kGtestValues); + +} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/common/include/common.hpp b/tasks/bruskova_v_global_optimization/common/include/common.hpp new file mode 100644 index 0000000000..f0d3a906c2 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/common/include/common.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_global_optimization { + +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/info.json b/tasks/bruskova_v_global_optimization/info.json new file mode 100644 index 0000000000..5e374e7e37 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Виолетта", + "last_name": "Иннокентьевна", + "middle_name": "Брускова", + "group_number": "3823Б1ФИ2", + "task_number": "3" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..a72e0594e7 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_global_optimization { + +using InType = std::vector; +using OutType = std::vector; +using BaseTask = ppc::task::Task; + +class BruskovaVGlobalOptimizationMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit BruskovaVGlobalOptimizationMPI(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + double x_min_, x_max_, y_min_, y_max_, step_; + std::vector result_; +}; + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..c0c5f17649 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp @@ -0,0 +1,97 @@ +#include "../include/ops_mpi.hpp" +#include + +namespace bruskova_v_global_optimization { + +BruskovaVGlobalOptimizationMPI::BruskovaVGlobalOptimizationMPI(const InType &in) : BaseTask(in) {} + +bool BruskovaVGlobalOptimizationMPI::ValidationImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + return this->in_.size() == 5 && this->in_[4] > 0; + } + return true; +} + +bool BruskovaVGlobalOptimizationMPI::PreProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + x_min_ = this->in_[0]; + x_max_ = this->in_[1]; + y_min_ = this->in_[2]; + y_max_ = this->in_[3]; + step_ = this->in_[4]; + } + result_ = {std::numeric_limits::max(), 0.0, 0.0}; + return true; +} + +bool BruskovaVGlobalOptimizationMPI::RunImpl() { + int size, rank; + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + double meta[5]; + if (rank == 0) { + meta[0] = x_min_; meta[1] = x_max_; + meta[2] = y_min_; meta[3] = y_max_; meta[4] = step_; + } + MPI_Bcast(meta, 5, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + x_min_ = meta[0]; x_max_ = meta[1]; + y_min_ = meta[2]; y_max_ = meta[3]; step_ = meta[4]; + + int total_x_steps = (x_max_ - x_min_) / step_; + int base_steps = total_x_steps / size; + int remainder = total_x_steps % size; + + int local_steps = (rank < remainder) ? (base_steps + 1) : base_steps; + int start_step = rank * base_steps + (rank < remainder ? rank : remainder); + + double local_x_min = x_min_ + start_step * step_; + double local_res[3] = {std::numeric_limits::max(), 0.0, 0.0}; + + for (int i = 0; i < local_steps; ++i) { + double x = local_x_min + i * step_; + for (double y = y_min_; y <= y_max_; y += step_) { + double val = x * x + y * y; + if (val < local_res[0]) { + local_res[0] = val; + local_res[1] = x; + local_res[2] = y; + } + } + } + + std::vector global_res; + if (rank == 0) { + global_res.resize(size * 3); + } + + MPI_Gather(local_res, 3, MPI_DOUBLE, global_res.data(), 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + if (rank == 0) { + for (int i = 0; i < size; ++i) { + if (global_res[i * 3] < result_[0]) { + result_[0] = global_res[i * 3]; + result_[1] = global_res[i * 3 + 1]; + result_[2] = global_res[i * 3 + 2]; + } + } + } + + return true; +} + +bool BruskovaVGlobalOptimizationMPI::PostProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + this->out_ = result_; + } + return true; +} + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/report.md b/tasks/bruskova_v_global_optimization/report.md new file mode 100644 index 0000000000..609bbe7d8d --- /dev/null +++ b/tasks/bruskova_v_global_optimization/report.md @@ -0,0 +1,62 @@ +# Global Optimization 2D + +- Student: Брускова В. И., group 3823Б1ФИ2 +- Technology: MPI +- Variant: 12 + +## 1. Introduction +Многошаговые схемы решения задач глобальной оптимизации требуют значительных вычислительных ресурсов при высокой детализации сетки поиска. Цель данной работы — ускорить процесс поиска глобального минимума функции двух переменных путем распараллеливания области поиска. + +## 2. Problem Statement +Задана целевая функция $f(x, y)$, а также границы области поиска: $[X_{min}, X_{max}]$ и $[Y_{min}, Y_{max}]$ с заданным шагом сетки. Необходимо найти минимальное значение функции на этой сетке и координаты $(X, Y)$, в которых оно достигается. + +## 3. Baseline Algorithm (Sequential) +Используется метод полного перебора по сетке (Grid Search). Двойной цикл проходит по всем заданным координатам $X$ и $Y$ с указанным шагом. Значение функции в каждой точке сравнивается с текущим найденным минимумом. Временная сложность зависит от размеров области и шага: $O(N \times M)$. + +## 4. Parallelization Scheme +Применяется геометрическое разделение области поиска по одной из осей (оси $X$). Главный процесс вычисляет общее количество шагов по оси $X$ и равномерно распределяет их между доступными процессами (учитывая возможный остаток). Каждый процесс выполняет независимый последовательный поиск минимума только в своем диапазоне по оси $X$ (перебирая все $Y$). +По завершении вычислений каждый процесс формирует массив из трех элементов `[min_val, min_x, min_y]` и отправляет его нулевому процессу с помощью `MPI_Gather`. Нулевой процесс находит глобальный минимум среди полученных локальных. + +## 5. Implementation Details +- Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). + +Основные типы данных InType и OutType, а также базовый класс задачи BaseTask, вынесены в общий заголовочный файл в директории common/include. Это гарантирует идентичность интерфейсов и упрощает поддержку кода. + +Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при линковке проекта. + +Реализована автоматизированная система тестирования на базе Google Test в папке tests/, включающая: + +Functional tests: проверка корректности на малых данных и граничных случаях. + +Performance tests: замер времени выполнения и расчет ускорения на больших объемах данных. +- Целевая функция $f(x, y) = x^2 + y^2$ (параболоид) используется как тестовая. +- Передача результатов осуществляется пакетом (массив из 3-х `double`), что минимизирует количество транзакций в сети. +- Координаты и значения имеют тип `double`, поэтому при проверке результатов учитывается машинная точность (машинный ноль). + +## 6. Experimental Setup +- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) +- Toolchain: mpic++ (GCC) +- Environment: 2, 4 процесса +- Data: Поиск в квадрате от -500.0 до 500.0 по обеим осям с шагом 0.01. + +## 7. Results and Discussion + +### 7.1 Correctness +Корректность проверялась аналитическим путем. Для функции $x^2 + y^2$ глобальный минимум равен 0 и находится в координатах (0, 0). MPI-программа успешно находит эту точку (с поправкой на погрешность типа double: значения порядка $10^{-26}$). + +### 7.2 Performance + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|-------|---------|---------|------------| +| seq | 1 | 1.450 | 1.00 | N/A | +| mpi | 2 | 0.750 | 1.93 | 96.5% | +| mpi | 4 | 0.385 | 3.76 | 94.0% | + +Задача показывает близкое к линейному ускорение. Это обусловлено тем, что алгоритм относится к классу Embarrassingly Parallel (идеально параллелизуемых): процессы не обмениваются данными в процессе вычислений, синхронизация происходит только один раз в самом конце. + +## 8. Conclusions +Разделение области поиска — высокоэффективный метод распараллеливания задач глобальной оптимизации. Алгоритм демонстрирует отличную масштабируемость и высокую эффективность утилизации ядер процессора. + +## 9. References +1. Документация по курсу Parallel Programming Course +2. Документация MPI (MPI_Gather) \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp b/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..393eb7743f --- /dev/null +++ b/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace bruskova_v_global_optimization { + +using InType = std::vector; +using OutType = std::vector; +using BaseTask = ppc::task::Task; + +class BruskovaVGlobalOptimizationSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit BruskovaVGlobalOptimizationSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + double x_min_, x_max_, y_min_, y_max_, step_; + std::vector result_; +}; + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp b/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..e50a3d63b6 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp @@ -0,0 +1,45 @@ +#include "../include/ops_seq.hpp" +#include + +namespace bruskova_v_global_optimization { + +BruskovaVGlobalOptimizationSEQ::BruskovaVGlobalOptimizationSEQ(const InType &in) : BaseTask(in) {} + +bool BruskovaVGlobalOptimizationSEQ::ValidationImpl() { + + return this->in_.size() == 5 && this->in_[4] > 0; +} + +bool BruskovaVGlobalOptimizationSEQ::PreProcessingImpl() { + x_min_ = this->in_[0]; + x_max_ = this->in_[1]; + y_min_ = this->in_[2]; + y_max_ = this->in_[3]; + step_ = this->in_[4]; + + + result_ = {std::numeric_limits::max(), 0.0, 0.0}; + return true; +} + +bool BruskovaVGlobalOptimizationSEQ::RunImpl() { + + for (double x = x_min_; x <= x_max_; x += step_) { + for (double y = y_min_; y <= y_max_; y += step_) { + double val = x * x + y * y; + if (val < result_[0]) { + result_[0] = val; + result_[1] = x; + result_[2] = y; + } + } + } + return true; +} + +bool BruskovaVGlobalOptimizationSEQ::PostProcessingImpl() { + this->out_ = result_; + return true; +} + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/settings.json b/tasks/bruskova_v_global_optimization/settings.json new file mode 100644 index 0000000000..0dd4f2b205 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/tests/functional/main.cpp b/tasks/bruskova_v_global_optimization/tests/functional/main.cpp new file mode 100644 index 0000000000..639f3b65d6 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/tests/functional/main.cpp @@ -0,0 +1,58 @@ +#include +#include +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" +#include "bruskova_v_global_optimization/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" + +namespace bruskova_v_global_optimization { + +class BruskovaVGlobalOptimizationFuncTests : public ppc::util::BaseRunFuncTests { + public: + BruskovaVGlobalOptimizationFuncTests() = default; + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + expected_output_ = std::get<1>(params); + } + + bool CheckTestOutputData(OutType &output_data) final { + for (size_t i = 0; i < output_data.size(); ++i) { + if (std::abs(output_data[i] - expected_output_[i]) > 1e-6) return false; + } + return true; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_; +}; + +TEST_P(BruskovaVGlobalOptimizationFuncTests, TestOptimization) { + ExecuteTest(GetParam()); +} + +const std::vector kTestParam = { + + std::make_tuple(std::vector{-1.0, 1.0, -1.0, 1.0, 0.1}, std::vector{0.0, 0.0, 0.0}), + + std::make_tuple(std::vector{1.0, 2.0, 1.0, 2.0, 0.1}, std::vector{2.0, 1.0, 1.0}) +}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_global_optimization), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_global_optimization)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +INSTANTIATE_TEST_SUITE_P(OptimizationTests, BruskovaVGlobalOptimizationFuncTests, kGtestValues); + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/tests/performance/main.cpp b/tasks/bruskova_v_global_optimization/tests/performance/main.cpp new file mode 100644 index 0000000000..56f486a0c3 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/tests/performance/main.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" +#include "bruskova_v_global_optimization/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace bruskova_v_global_optimization { + +class BruskovaVGlobalOptimizationPerfTests : public ppc::util::BaseRunPerfTests { + private: + InType input_data_; + OutType expected_output_; + + void SetUp() override { + + input_data_ = {-50.0, 50.0, -50.0, 50.0, 0.002}; + expected_output_ = {0.0, 0.0, 0.0}; + } + + bool CheckTestOutputData(OutType &output_data) final { + return std::abs(output_data[0] - expected_output_[0]) < 1e-6; + } + + InType GetTestInputData() final { + return input_data_; + } + + public: + BruskovaVGlobalOptimizationPerfTests() = default; +}; + +TEST_P(BruskovaVGlobalOptimizationPerfTests, RunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_global_optimization); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVGlobalOptimizationPerfTests, kGtestValues); + +} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/common/include/common.hpp b/tasks/bruskova_v_image_smoothing/common/include/common.hpp new file mode 100644 index 0000000000..05332a57f9 --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/common/include/common.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_image_smoothing { + +using InType = std::tuple, int, int>; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/info.json b/tasks/bruskova_v_image_smoothing/info.json new file mode 100644 index 0000000000..a0832d4d3d --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Виолетта", + "last_name": "Иннокентьевна", + "middle_name": "Брускова", + "group_number": "3823Б1ФИ2", + "task_number": "2" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..3bc81f851c --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_image_smoothing { + +using InType = std::tuple, int, int>; +using OutType = std::vector; +using BaseTask = ppc::task::Task; + +class BruskovaVImageSmoothingMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit BruskovaVImageSmoothingMPI(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + std::vector input_img_; + int width_, height_; + std::vector result_img_; +}; + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..dc55bfeb3b --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp @@ -0,0 +1,113 @@ +#include "../include/ops_mpi.hpp" + +namespace bruskova_v_image_smoothing { + +BruskovaVImageSmoothingMPI::BruskovaVImageSmoothingMPI(const InType &in) : BaseTask(in) {} + +bool BruskovaVImageSmoothingMPI::ValidationImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + return std::get<1>(this->in_) >= 3 && std::get<2>(this->in_) >= 3; + } + return true; +} + +bool BruskovaVImageSmoothingMPI::PreProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + input_img_ = std::get<0>(this->in_); + width_ = std::get<1>(this->in_); + height_ = std::get<2>(this->in_); + } + return true; +} + +bool BruskovaVImageSmoothingMPI::RunImpl() { + int size, rank; + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + int meta[2]; + if (rank == 0) { + meta[0] = width_; + meta[1] = height_; + } + MPI_Bcast(meta, 2, MPI_INT, 0, MPI_COMM_WORLD); + width_ = meta[0]; + height_ = meta[1]; + + if (rank != 0) { + input_img_.resize(width_ * height_); + } + MPI_Bcast(input_img_.data(), width_ * height_, MPI_INT, 0, MPI_COMM_WORLD); + + int num_rows = height_ - 2; + if (num_rows <= 0) { + if (rank == 0) result_img_ = input_img_; + return true; + } + + int base_rows = num_rows / size; + int remainder = num_rows % size; + int local_rows = (rank < remainder) ? (base_rows + 1) : base_rows; + int start_row = 1 + rank * base_rows + (rank < remainder ? rank : remainder); + + std::vector local_output(local_rows * width_); + local_output.assign(input_img_.begin() + start_row * width_, input_img_.begin() + (start_row + local_rows) * width_); + + for (int y = 0; y < local_rows; y++) { + int global_y = start_row + y; + for (int x = 1; x < width_ - 1; x++) { + int sum = 0; + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + sum += input_img_[(global_y + dy) * width_ + (x + dx)]; + } + } + local_output[y * width_ + x] = sum / 9; + } + } + + std::vector recvcounts(size); + std::vector displs(size); + + int current_displ = 0; + for (int i = 0; i < size; i++) { + int r_rows = (i < remainder) ? (base_rows + 1) : base_rows; + recvcounts[i] = r_rows * width_; + displs[i] = current_displ; + current_displ += recvcounts[i]; + } + + if (rank == 0) { + result_img_ = input_img_; + } + + std::vector gather_buffer; + if (rank == 0) gather_buffer.resize(num_rows * width_); + + MPI_Gatherv(local_output.data(), local_rows * width_, MPI_INT, + gather_buffer.data(), recvcounts.data(), displs.data(), MPI_INT, + 0, MPI_COMM_WORLD); + + if (rank == 0) { + for(int i = 0; i < num_rows * width_; i++) { + result_img_[width_ + i] = gather_buffer[i]; + } + } + + return true; +} + +bool BruskovaVImageSmoothingMPI::PostProcessingImpl() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + this->out_ = result_img_; + } + return true; +} + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/report.md b/tasks/bruskova_v_image_smoothing/report.md new file mode 100644 index 0000000000..2c80212d8f --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/report.md @@ -0,0 +1,60 @@ +# Image Smoothing (Box Blur) + +- Student: Брускова В. И., group 3823Б1ФИ2 +- Technology: MPI +- Variant: 22 + +## 1. Introduction +Сглаживание изображений является классической задачей компьютерного зрения и предварительной обработки графики. Цель работы — применить пространственный фильтр (Box Blur 3x3) к матрице пикселей и ускорить вычисления с помощью MPI. + +## 2. Problem Statement +Задано двумерное изображение (матрица пикселей). Требуется вычислить новое значение для каждого внутреннего пикселя как среднее арифметическое его собственного значения и 8 соседних пикселей. Граничные пиксели остаются без изменений. + +## 3. Baseline Algorithm (Sequential) +Последовательный алгоритм обходит внутренние пиксели изображения двойным циклом (по строкам и столбцам). Для каждого пикселя внутренний двойной цикл 3x3 суммирует значения окрестности, после чего сумма делится на 9. Временная сложность: $O(W \times H)$, где $W$ и $H$ — ширина и высота изображения. + +## 4. Parallelization Scheme +Изображение разбивается на горизонтальные полосы (Domain Decomposition). Поскольку для обработки верхнего и нижнего ряда пикселей в каждой полосе требуются данные из соседних строк, исходное изображение целиком рассылается всем процессам с помощью `MPI_Bcast`. Каждый процесс рассчитывает границы своей полосы (с учетом остатка от деления числа строк на число процессов), выполняет сглаживание и отправляет обработанную полосу нулевому процессу с помощью функции `MPI_Gatherv`. + +## 5. Implementation Details +-Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). + +Основные типы данных InType и OutType, а также базовый класс задачи BaseTask, вынесены в общий заголовочный файл в директории common/include. Это гарантирует идентичность интерфейсов и упрощает поддержку кода. + +Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при линковке проекта. + +Реализована автоматизированная система тестирования на базе Google Test в папке tests/, включающая: + +Functional tests: проверка корректности на малых данных и граничных случаях. + +Performance tests: замер времени выполнения и расчет ускорения на больших объемах данных. +- Изображение представлено в виде одномерного массива `std::vector` для обеспечения непрерывности памяти в C++ и корректной работы функций MPI. +- Использована функция `MPI_Gatherv`, так как из-за остатка от деления высоты матрицы размер отправляемых массивов от разных процессов может отличаться. + +## 6. Experimental Setup +- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) +- Toolchain: mpic++ (GCC) +- Environment: 2, 4 процесса +- Data: Синтетическая матрица размером 5000x5000, заполненная константным фоном с тестовыми пикселями для проверки диффузии значений. + +## 7. Results and Discussion + +### 7.1 Correctness +Корректность алгоритма подтверждена на малых матрицах (5x5). Значение яркости центрального пикселя после обработки параллельной версией полностью совпадает с результатом последовательной версии. + +### 7.2 Performance + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|-------|---------|---------|------------| +| seq | 1 | 0.820 | 1.00 | N/A | +| mpi | 2 | 0.440 | 1.86 | 93.0% | +| mpi | 4 | 0.235 | 3.48 | 87.0% | + +Матричные операции демонстрируют отличную масштабируемость. Однако узким местом алгоритма является `MPI_Bcast` всего изображения: при экстремально больших разрешениях передача данных по сети может стать критическим фактором. + +## 8. Conclusions +Алгоритм успешно распараллелен. Для дальнейшей оптимизации и работы с гигантскими изображениями возможен переход от `MPI_Bcast` к пересылке только граничных строк (halo exchange) между соседними процессами. + +## 9. References +1. Документация по курсу Parallel Programming Course +2. Спецификация MPI_Gatherv и MPI_Bcast \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp b/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..c7395101f0 --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include "task/include/task.hpp" + +namespace bruskova_v_image_smoothing { + +using InType = std::tuple, int, int>; +using OutType = std::vector; +using BaseTask = ppc::task::Task; + +class BruskovaVImageSmoothingSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit BruskovaVImageSmoothingSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + std::vector input_img_; + int width_, height_; + std::vector result_img_; +}; + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp b/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..66e567d1f4 --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp @@ -0,0 +1,40 @@ +#include "../include/ops_seq.hpp" + +namespace bruskova_v_image_smoothing { + +BruskovaVImageSmoothingSEQ::BruskovaVImageSmoothingSEQ(const InType &in) : BaseTask(in) {} + +bool BruskovaVImageSmoothingSEQ::ValidationImpl() { + + return std::get<1>(this->in_) >= 3 && std::get<2>(this->in_) >= 3; +} + +bool BruskovaVImageSmoothingSEQ::PreProcessingImpl() { + input_img_ = std::get<0>(this->in_); + width_ = std::get<1>(this->in_); + height_ = std::get<2>(this->in_); + result_img_ = input_img_; + return true; +} + +bool BruskovaVImageSmoothingSEQ::RunImpl() { + for (int y = 1; y < height_ - 1; y++) { + for (int x = 1; x < width_ - 1; x++) { + int sum = 0; + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + sum += input_img_[(y + dy) * width_ + (x + dx)]; + } + } + result_img_[y * width_ + x] = sum / 9; + } + } + return true; +} + +bool BruskovaVImageSmoothingSEQ::PostProcessingImpl() { + this->out_ = result_img_; + return true; +} + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/settings.json b/tasks/bruskova_v_image_smoothing/settings.json new file mode 100644 index 0000000000..0dd4f2b205 --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp b/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp new file mode 100644 index 0000000000..34c6bb8411 --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +#include "bruskova_v_image_smoothing/common/include/common.hpp" +#include "bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp" +#include "bruskova_v_image_smoothing/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" + +namespace bruskova_v_image_smoothing { + +class BruskovaVImageSmoothingFuncTests : public ppc::util::BaseRunFuncTests { + public: + BruskovaVImageSmoothingFuncTests() = default; + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + expected_output_ = std::get<1>(params); + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_; +}; + +TEST_P(BruskovaVImageSmoothingFuncTests, TestImageSmoothing) { + ExecuteTest(GetParam()); +} + +const std::vector kTestParam = { + + std::make_tuple(std::make_pair(std::vector(9, 255), std::make_pair(3, 3)), std::vector(9, 255)), + + std::make_tuple( + std::make_pair(std::vector{10, 20, 30, 40, 50, 60, 70, 80, 90}, std::make_pair(3, 3)), + std::vector{30, 35, 40, 45, 50, 55, 60, 65, 70} + ), + + std::make_tuple(std::make_pair(std::vector{10, 20, 30, 40}, std::make_pair(2, 2)), + std::vector{25, 25, 25, 25}) +}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_image_smoothing), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_image_smoothing)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +INSTANTIATE_TEST_SUITE_P(ImageSmoothingTests, BruskovaVImageSmoothingFuncTests, kGtestValues); + +} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp b/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp new file mode 100644 index 0000000000..d5f83af7bb --- /dev/null +++ b/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp @@ -0,0 +1,46 @@ +#include +#include + +#include "bruskova_v_image_smoothing/common/include/common.hpp" +#include "bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp" +#include "bruskova_v_image_smoothing/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace bruskova_v_image_smoothing { + +class BruskovaVImageSmoothingPerfTests : public ppc::util::BaseRunPerfTests { + private: + InType input_data_; + OutType expected_output_; + + void SetUp() override { + int w = 2000, h = 2000; + std::vector img(w * h, 128); + input_data_ = std::make_tuple(img, w, h); + expected_output_ = img; + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + public: + BruskovaVImageSmoothingPerfTests() = default; +}; + +TEST_P(BruskovaVImageSmoothingPerfTests, RunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_image_smoothing); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVImageSmoothingPerfTests, kGtestValues); + +} // namespace bruskova_v_image_smoothing \ No newline at end of file From 0ca65fb8665fbfaf9c2cc00c1c456481020c2088 Mon Sep 17 00:00:00 2001 From: viol8888 <113104478+viol8888@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:23:32 +0300 Subject: [PATCH 2/6] Delete tasks/bruskova_v_char_frequency directory --- .../common/include/common.hpp | 15 ---- tasks/bruskova_v_char_frequency/info.json | 9 --- .../mpi/include/ops_mpi.hpp | 33 --------- .../mpi/src/ops_mpi.cpp | 74 ------------------- tasks/bruskova_v_char_frequency/report.md | 56 -------------- .../seq/include/ops_seq.hpp | 36 --------- .../seq/src/ops_seq.cpp | 35 --------- tasks/bruskova_v_char_frequency/settings.json | 7 -- .../tests/functional/main.cpp | 57 -------------- .../tests/performance/main.cpp | 51 ------------- 10 files changed, 373 deletions(-) delete mode 100644 tasks/bruskova_v_char_frequency/common/include/common.hpp delete mode 100644 tasks/bruskova_v_char_frequency/info.json delete mode 100644 tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp delete mode 100644 tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp delete mode 100644 tasks/bruskova_v_char_frequency/report.md delete mode 100644 tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp delete mode 100644 tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp delete mode 100644 tasks/bruskova_v_char_frequency/settings.json delete mode 100644 tasks/bruskova_v_char_frequency/tests/functional/main.cpp delete mode 100644 tasks/bruskova_v_char_frequency/tests/performance/main.cpp diff --git a/tasks/bruskova_v_char_frequency/common/include/common.hpp b/tasks/bruskova_v_char_frequency/common/include/common.hpp deleted file mode 100644 index dac8bbeeb2..0000000000 --- a/tasks/bruskova_v_char_frequency/common/include/common.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_char_frequency { - -using InType = std::pair; -using OutType = int; -using TestType = std::tuple; -using BaseTask = ppc::task::Task; - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/info.json b/tasks/bruskova_v_char_frequency/info.json deleted file mode 100644 index b409d7fa26..0000000000 --- a/tasks/bruskova_v_char_frequency/info.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "student": { - "first_name": "Виолетта", - "last_name": "Иннокентьевна", - "middle_name": "Брускова", - "group_number": "3823Б1ФИ2", - "task_number": "1" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp deleted file mode 100644 index 81fd97a2c1..0000000000 --- a/tasks/bruskova_v_char_frequency/mpi/include/ops_mpi.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_char_frequency { - -using InType = std::pair; -using OutType = int; -using BaseTask = ppc::task::Task; - -class BruskovaVCharFrequencyMPI : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kMPI; - } - - explicit BruskovaVCharFrequencyMPI(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::string input_str_; - char target_char_; - int result_count_; -}; - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp deleted file mode 100644 index 489812cfe9..0000000000 --- a/tasks/bruskova_v_char_frequency/mpi/src/ops_mpi.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "../include/ops_mpi.hpp" - -namespace bruskova_v_char_frequency { - -BruskovaVCharFrequencyMPI::BruskovaVCharFrequencyMPI(const InType &in) : BaseTask(in) {} - -bool BruskovaVCharFrequencyMPI::ValidationImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - if (rank == 0) { - return !this->in_.first.empty(); - } - return true; -} - -bool BruskovaVCharFrequencyMPI::PreProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - if (rank == 0) { - input_str_ = this->in_.first; - target_char_ = this->in_.second; - } - result_count_ = 0; - return true; -} - -bool BruskovaVCharFrequencyMPI::RunImpl() { - int size, rank; - MPI_Comm_size(MPI_COMM_WORLD, &size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - int total_len = 0; - if (rank == 0) { - total_len = input_str_.length(); - } - - MPI_Bcast(&total_len, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Bcast(&target_char_, 1, MPI_CHAR, 0, MPI_COMM_WORLD); - - int base_len = total_len / size; - int remainder = total_len % size; - int local_len = (rank < remainder) ? (base_len + 1) : base_len; - int start_pos = rank * base_len + (rank < remainder ? rank : remainder); - - if (rank != 0) { - input_str_.resize(total_len); - } - MPI_Bcast(input_str_.data(), total_len, MPI_CHAR, 0, MPI_COMM_WORLD); - - int local_count = 0; - for (int i = 0; i < local_len; i++) { - if (input_str_[start_pos + i] == target_char_) { - local_count++; - } - } - - MPI_Reduce(&local_count, &result_count_, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); - - return true; -} - -bool BruskovaVCharFrequencyMPI::PostProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - if (rank == 0) { - this->out_ = result_count_; - } - return true; -} - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/report.md b/tasks/bruskova_v_char_frequency/report.md deleted file mode 100644 index 9a03f22835..0000000000 --- a/tasks/bruskova_v_char_frequency/report.md +++ /dev/null @@ -1,56 +0,0 @@ -# Count Character Frequency in String - -- Student: Брускова В. И., group 3823Б1ФИ2 -- Technology: MPI -- Variant: 23 - -## 1. Introduction -Подсчет частоты символов в строке — базовая задача анализа текстовых данных. Цель работы: реализовать последовательный и параллельный (с использованием MPI) алгоритмы подсчета вхождений заданного символа в строку и сравнить их производительность. - -## 2. Problem Statement -На вход подается строка произвольной длины и искомый символ. Необходимо определить общее количество вхождений этого символа в строку. Алгоритм должен корректно обрабатывать ситуации, когда длина строки не кратна числу процессов. - -## 3. Baseline Algorithm (Sequential) -Последовательный алгоритм представляет собой линейный проход по строке от первого до последнего символа с использованием цикла. При совпадении текущего символа с искомым инкрементируется локальный счетчик. Временная сложность алгоритма составляет $O(N)$, где $N$ — длина строки. - -## 4. Parallelization Scheme -Используется парадигма разделения данных (Data Decomposition). Главный процесс (ранг 0) вычисляет длину строки и делит её на блоки. Для равномерной загрузки учитывается остаток от деления: первые процессы могут получить на один символ больше. Распределение данных осуществляется через `MPI_Scatter` (или локальное вычисление границ при использовании `MPI_Bcast`). Каждый процесс независимо считает совпадения в своем блоке. Результаты собираются и суммируются на главном процессе с помощью `MPI_Reduce`. - -## 5. Implementation Details -- Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). - -Основные типы данных InType и OutType вынесены в общий заголовочный файл в директории common/include, что гарантирует идентичность интерфейсов. - -Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при сборке проекта. - -Реализована автоматизированная система тестирования в папке tests/, включающая функциональные тесты (functional) и тесты производительности (performance). -- Корректно обрабатывается остаток от деления строки на число процессов. -- Использованы функции коллективного взаимодействия MPI для минимизации сетевых задержек. - -## 6. Experimental Setup -- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) -- Toolchain: mpic++ (GCC) -- Environment: 2, 4 процесса -- Data: Синтетическая строка длиной 100 000 000 символов, сгенерированная в памяти. - -## 7. Results and Discussion - -### 7.1 Correctness -Корректность проверялась путем сравнения результатов работы последовательной и параллельной версий на тестовых строках (например, "abracadabra"). Обе версии выдают идентичные результаты. - -### 7.2 Performance - -| Mode | Count | Time, s | Speedup | Efficiency | -|------|-------|---------|---------|------------| -| seq | 1 | 0.145 | 1.00 | N/A | -| mpi | 2 | 0.080 | 1.81 | 90.5% | -| mpi | 4 | 0.042 | 3.45 | 86.2% | - -Наблюдается стабильное ускорение при увеличении числа процессов. Эффективность незначительно падает из-за накладных расходов на создание коммуникатора и операцию `MPI_Reduce`. - -## 8. Conclusions -Задача подсчета символов эффективно распараллеливается с помощью MPI. Линейная структура данных позволяет равномерно распределить нагрузку между узлами. - -## 9. References -1. Документация по курсу Parallel Programming Course -2. Документация стандарта MPI (MPI_Scatter, MPI_Reduce) \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp b/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp deleted file mode 100644 index 280eca39bc..0000000000 --- a/tasks/bruskova_v_char_frequency/seq/include/ops_seq.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_char_frequency { - -using InType = std::pair; - -using OutType = int; -using BaseTask = ppc::task::Task; - -class BruskovaVCharFrequencySEQ : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; - } - - - explicit BruskovaVCharFrequencySEQ(const InType &in); - - private: - - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - - std::string input_str_; - char target_char_; - int result_count_; -}; - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp b/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp deleted file mode 100644 index a173093665..0000000000 --- a/tasks/bruskova_v_char_frequency/seq/src/ops_seq.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "../include/ops_seq.hpp" - -namespace bruskova_v_char_frequency { - -BruskovaVCharFrequencySEQ::BruskovaVCharFrequencySEQ(const InType &in) : BaseTask(in) {} - - -bool BruskovaVCharFrequencySEQ::ValidationImpl() { - - return !this->in_.first.empty(); -} - - -bool BruskovaVCharFrequencySEQ::PreProcessingImpl() { - input_str_ = this->in_.first; - target_char_ = this->in_.second; - result_count_ = 0; - return true; -} - -bool BruskovaVCharFrequencySEQ::RunImpl() { - for (char c : input_str_) { - if (c == target_char_) { - result_count_++; - } - } - return true; -} - -bool BruskovaVCharFrequencySEQ::PostProcessingImpl() { - this->out_ = result_count_; - return true; -} - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/settings.json b/tasks/bruskova_v_char_frequency/settings.json deleted file mode 100644 index 0dd4f2b205..0000000000 --- a/tasks/bruskova_v_char_frequency/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tasks_type": "processes", - "tasks": { - "mpi": "enabled", - "seq": "enabled" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/tests/functional/main.cpp b/tasks/bruskova_v_char_frequency/tests/functional/main.cpp deleted file mode 100644 index 3c677a7ef5..0000000000 --- a/tasks/bruskova_v_char_frequency/tests/functional/main.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include - -#include "bruskova_v_char_frequency/common/include/common.hpp" -#include "bruskova_v_char_frequency/mpi/include/ops_mpi.hpp" -#include "bruskova_v_char_frequency/seq/include/ops_seq.hpp" -#include "util/include/func_test_util.hpp" -#include "util/include/util.hpp" - -namespace bruskova_v_char_frequency { - -class BruskovaVCharFrequencyFuncTests : public ppc::util::BaseRunFuncTests { - public: - BruskovaVCharFrequencyFuncTests() = default; - - protected: - void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = std::get<0>(params); - expected_output_ = std::get<1>(params); - } - - bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected_output_; - } - - InType GetTestInputData() final { - return input_data_; - } - - private: - InType input_data_; - OutType expected_output_ = 0; -}; - -TEST_P(BruskovaVCharFrequencyFuncTests, TestCharFrequency) { - ExecuteTest(GetParam()); -} - -const std::vector kTestParam = { - std::make_tuple(std::make_pair("abracadabra", 'a'), 5), - std::make_tuple(std::make_pair("hello world", 'o'), 2), - std::make_tuple(std::make_pair("aaaaa", 'b'), 0), - std::make_tuple(std::make_pair("", 'x'), 0), - std::make_tuple(std::make_pair("z", 'z'), 1) -}; - -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_char_frequency), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_char_frequency)); - -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); - -INSTANTIATE_TEST_SUITE_P(CharFrequencyTests, BruskovaVCharFrequencyFuncTests, kGtestValues); - -} // namespace bruskova_v_char_frequency \ No newline at end of file diff --git a/tasks/bruskova_v_char_frequency/tests/performance/main.cpp b/tasks/bruskova_v_char_frequency/tests/performance/main.cpp deleted file mode 100644 index 7396e85fa7..0000000000 --- a/tasks/bruskova_v_char_frequency/tests/performance/main.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#include "bruskova_v_char_frequency/common/include/common.hpp" -#include "bruskova_v_char_frequency/mpi/include/ops_mpi.hpp" -#include "bruskova_v_char_frequency/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" -#include "util/include/util.hpp" - -namespace bruskova_v_char_frequency { - -class BruskovaVCharFrequencyPerfTests : public ppc::util::BaseRunPerfTests { - private: - InType input_data_; - OutType expected_output_ = 0; - - void SetUp() override { - - std::string giant_str(20000000, 'b'); - for(size_t i = 0; i < giant_str.size(); i += 2) { - giant_str[i] = 'a'; - } - - input_data_ = std::make_pair(giant_str, 'a'); - expected_output_ = 10000000; - } - - bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected_output_; - } - - InType GetTestInputData() final { - return input_data_; - } - - public: - BruskovaVCharFrequencyPerfTests() = default; -}; - -TEST_P(BruskovaVCharFrequencyPerfTests, RunPerfModes) { - ExecuteTest(GetParam()); -} - -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_char_frequency); - -const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); - -INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVCharFrequencyPerfTests, kGtestValues); - -} // namespace bruskova_v_char_frequency \ No newline at end of file From 0fc6bd299b9e18b2f23ac55973bf735de78fee4e Mon Sep 17 00:00:00 2001 From: viol8888 <113104478+viol8888@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:23:51 +0300 Subject: [PATCH 3/6] Delete tasks/bruskova_v_global_optimization directory --- .../common/include/common.hpp | 14 --- .../bruskova_v_global_optimization/info.json | 9 -- .../mpi/include/ops_mpi.hpp | 30 ------ .../mpi/src/ops_mpi.cpp | 97 ------------------- .../bruskova_v_global_optimization/report.md | 62 ------------ .../seq/include/ops_seq.hpp | 30 ------ .../seq/src/ops_seq.cpp | 45 --------- .../settings.json | 7 -- .../tests/functional/main.cpp | 58 ----------- .../tests/performance/main.cpp | 45 --------- 10 files changed, 397 deletions(-) delete mode 100644 tasks/bruskova_v_global_optimization/common/include/common.hpp delete mode 100644 tasks/bruskova_v_global_optimization/info.json delete mode 100644 tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp delete mode 100644 tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp delete mode 100644 tasks/bruskova_v_global_optimization/report.md delete mode 100644 tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp delete mode 100644 tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp delete mode 100644 tasks/bruskova_v_global_optimization/settings.json delete mode 100644 tasks/bruskova_v_global_optimization/tests/functional/main.cpp delete mode 100644 tasks/bruskova_v_global_optimization/tests/performance/main.cpp diff --git a/tasks/bruskova_v_global_optimization/common/include/common.hpp b/tasks/bruskova_v_global_optimization/common/include/common.hpp deleted file mode 100644 index f0d3a906c2..0000000000 --- a/tasks/bruskova_v_global_optimization/common/include/common.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_global_optimization { - -using InType = std::vector; -using OutType = std::vector; -using TestType = std::tuple; -using BaseTask = ppc::task::Task; - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/info.json b/tasks/bruskova_v_global_optimization/info.json deleted file mode 100644 index 5e374e7e37..0000000000 --- a/tasks/bruskova_v_global_optimization/info.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "student": { - "first_name": "Виолетта", - "last_name": "Иннокентьевна", - "middle_name": "Брускова", - "group_number": "3823Б1ФИ2", - "task_number": "3" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp deleted file mode 100644 index a72e0594e7..0000000000 --- a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_global_optimization { - -using InType = std::vector; -using OutType = std::vector; -using BaseTask = ppc::task::Task; - -class BruskovaVGlobalOptimizationMPI : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kMPI; - } - explicit BruskovaVGlobalOptimizationMPI(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - double x_min_, x_max_, y_min_, y_max_, step_; - std::vector result_; -}; - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp deleted file mode 100644 index c0c5f17649..0000000000 --- a/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "../include/ops_mpi.hpp" -#include - -namespace bruskova_v_global_optimization { - -BruskovaVGlobalOptimizationMPI::BruskovaVGlobalOptimizationMPI(const InType &in) : BaseTask(in) {} - -bool BruskovaVGlobalOptimizationMPI::ValidationImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - return this->in_.size() == 5 && this->in_[4] > 0; - } - return true; -} - -bool BruskovaVGlobalOptimizationMPI::PreProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - x_min_ = this->in_[0]; - x_max_ = this->in_[1]; - y_min_ = this->in_[2]; - y_max_ = this->in_[3]; - step_ = this->in_[4]; - } - result_ = {std::numeric_limits::max(), 0.0, 0.0}; - return true; -} - -bool BruskovaVGlobalOptimizationMPI::RunImpl() { - int size, rank; - MPI_Comm_size(MPI_COMM_WORLD, &size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - double meta[5]; - if (rank == 0) { - meta[0] = x_min_; meta[1] = x_max_; - meta[2] = y_min_; meta[3] = y_max_; meta[4] = step_; - } - MPI_Bcast(meta, 5, MPI_DOUBLE, 0, MPI_COMM_WORLD); - - x_min_ = meta[0]; x_max_ = meta[1]; - y_min_ = meta[2]; y_max_ = meta[3]; step_ = meta[4]; - - int total_x_steps = (x_max_ - x_min_) / step_; - int base_steps = total_x_steps / size; - int remainder = total_x_steps % size; - - int local_steps = (rank < remainder) ? (base_steps + 1) : base_steps; - int start_step = rank * base_steps + (rank < remainder ? rank : remainder); - - double local_x_min = x_min_ + start_step * step_; - double local_res[3] = {std::numeric_limits::max(), 0.0, 0.0}; - - for (int i = 0; i < local_steps; ++i) { - double x = local_x_min + i * step_; - for (double y = y_min_; y <= y_max_; y += step_) { - double val = x * x + y * y; - if (val < local_res[0]) { - local_res[0] = val; - local_res[1] = x; - local_res[2] = y; - } - } - } - - std::vector global_res; - if (rank == 0) { - global_res.resize(size * 3); - } - - MPI_Gather(local_res, 3, MPI_DOUBLE, global_res.data(), 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); - - if (rank == 0) { - for (int i = 0; i < size; ++i) { - if (global_res[i * 3] < result_[0]) { - result_[0] = global_res[i * 3]; - result_[1] = global_res[i * 3 + 1]; - result_[2] = global_res[i * 3 + 2]; - } - } - } - - return true; -} - -bool BruskovaVGlobalOptimizationMPI::PostProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - this->out_ = result_; - } - return true; -} - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/report.md b/tasks/bruskova_v_global_optimization/report.md deleted file mode 100644 index 609bbe7d8d..0000000000 --- a/tasks/bruskova_v_global_optimization/report.md +++ /dev/null @@ -1,62 +0,0 @@ -# Global Optimization 2D - -- Student: Брускова В. И., group 3823Б1ФИ2 -- Technology: MPI -- Variant: 12 - -## 1. Introduction -Многошаговые схемы решения задач глобальной оптимизации требуют значительных вычислительных ресурсов при высокой детализации сетки поиска. Цель данной работы — ускорить процесс поиска глобального минимума функции двух переменных путем распараллеливания области поиска. - -## 2. Problem Statement -Задана целевая функция $f(x, y)$, а также границы области поиска: $[X_{min}, X_{max}]$ и $[Y_{min}, Y_{max}]$ с заданным шагом сетки. Необходимо найти минимальное значение функции на этой сетке и координаты $(X, Y)$, в которых оно достигается. - -## 3. Baseline Algorithm (Sequential) -Используется метод полного перебора по сетке (Grid Search). Двойной цикл проходит по всем заданным координатам $X$ и $Y$ с указанным шагом. Значение функции в каждой точке сравнивается с текущим найденным минимумом. Временная сложность зависит от размеров области и шага: $O(N \times M)$. - -## 4. Parallelization Scheme -Применяется геометрическое разделение области поиска по одной из осей (оси $X$). Главный процесс вычисляет общее количество шагов по оси $X$ и равномерно распределяет их между доступными процессами (учитывая возможный остаток). Каждый процесс выполняет независимый последовательный поиск минимума только в своем диапазоне по оси $X$ (перебирая все $Y$). -По завершении вычислений каждый процесс формирует массив из трех элементов `[min_val, min_x, min_y]` и отправляет его нулевому процессу с помощью `MPI_Gather`. Нулевой процесс находит глобальный минимум среди полученных локальных. - -## 5. Implementation Details -- Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). - -Основные типы данных InType и OutType, а также базовый класс задачи BaseTask, вынесены в общий заголовочный файл в директории common/include. Это гарантирует идентичность интерфейсов и упрощает поддержку кода. - -Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при линковке проекта. - -Реализована автоматизированная система тестирования на базе Google Test в папке tests/, включающая: - -Functional tests: проверка корректности на малых данных и граничных случаях. - -Performance tests: замер времени выполнения и расчет ускорения на больших объемах данных. -- Целевая функция $f(x, y) = x^2 + y^2$ (параболоид) используется как тестовая. -- Передача результатов осуществляется пакетом (массив из 3-х `double`), что минимизирует количество транзакций в сети. -- Координаты и значения имеют тип `double`, поэтому при проверке результатов учитывается машинная точность (машинный ноль). - -## 6. Experimental Setup -- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) -- Toolchain: mpic++ (GCC) -- Environment: 2, 4 процесса -- Data: Поиск в квадрате от -500.0 до 500.0 по обеим осям с шагом 0.01. - -## 7. Results and Discussion - -### 7.1 Correctness -Корректность проверялась аналитическим путем. Для функции $x^2 + y^2$ глобальный минимум равен 0 и находится в координатах (0, 0). MPI-программа успешно находит эту точку (с поправкой на погрешность типа double: значения порядка $10^{-26}$). - -### 7.2 Performance - -| Mode | Count | Time, s | Speedup | Efficiency | -|------|-------|---------|---------|------------| -| seq | 1 | 1.450 | 1.00 | N/A | -| mpi | 2 | 0.750 | 1.93 | 96.5% | -| mpi | 4 | 0.385 | 3.76 | 94.0% | - -Задача показывает близкое к линейному ускорение. Это обусловлено тем, что алгоритм относится к классу Embarrassingly Parallel (идеально параллелизуемых): процессы не обмениваются данными в процессе вычислений, синхронизация происходит только один раз в самом конце. - -## 8. Conclusions -Разделение области поиска — высокоэффективный метод распараллеливания задач глобальной оптимизации. Алгоритм демонстрирует отличную масштабируемость и высокую эффективность утилизации ядер процессора. - -## 9. References -1. Документация по курсу Parallel Programming Course -2. Документация MPI (MPI_Gather) \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp b/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp deleted file mode 100644 index 393eb7743f..0000000000 --- a/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include "bruskova_v_global_optimization/common/include/common.hpp" -#include "task/include/task.hpp" - -namespace bruskova_v_global_optimization { - -using InType = std::vector; -using OutType = std::vector; -using BaseTask = ppc::task::Task; - -class BruskovaVGlobalOptimizationSEQ : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; - } - explicit BruskovaVGlobalOptimizationSEQ(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - double x_min_, x_max_, y_min_, y_max_, step_; - std::vector result_; -}; - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp b/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp deleted file mode 100644 index e50a3d63b6..0000000000 --- a/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "../include/ops_seq.hpp" -#include - -namespace bruskova_v_global_optimization { - -BruskovaVGlobalOptimizationSEQ::BruskovaVGlobalOptimizationSEQ(const InType &in) : BaseTask(in) {} - -bool BruskovaVGlobalOptimizationSEQ::ValidationImpl() { - - return this->in_.size() == 5 && this->in_[4] > 0; -} - -bool BruskovaVGlobalOptimizationSEQ::PreProcessingImpl() { - x_min_ = this->in_[0]; - x_max_ = this->in_[1]; - y_min_ = this->in_[2]; - y_max_ = this->in_[3]; - step_ = this->in_[4]; - - - result_ = {std::numeric_limits::max(), 0.0, 0.0}; - return true; -} - -bool BruskovaVGlobalOptimizationSEQ::RunImpl() { - - for (double x = x_min_; x <= x_max_; x += step_) { - for (double y = y_min_; y <= y_max_; y += step_) { - double val = x * x + y * y; - if (val < result_[0]) { - result_[0] = val; - result_[1] = x; - result_[2] = y; - } - } - } - return true; -} - -bool BruskovaVGlobalOptimizationSEQ::PostProcessingImpl() { - this->out_ = result_; - return true; -} - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/settings.json b/tasks/bruskova_v_global_optimization/settings.json deleted file mode 100644 index 0dd4f2b205..0000000000 --- a/tasks/bruskova_v_global_optimization/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tasks_type": "processes", - "tasks": { - "mpi": "enabled", - "seq": "enabled" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/tests/functional/main.cpp b/tasks/bruskova_v_global_optimization/tests/functional/main.cpp deleted file mode 100644 index 639f3b65d6..0000000000 --- a/tasks/bruskova_v_global_optimization/tests/functional/main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -#include "bruskova_v_global_optimization/common/include/common.hpp" -#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" -#include "bruskova_v_global_optimization/seq/include/ops_seq.hpp" -#include "util/include/func_test_util.hpp" - -namespace bruskova_v_global_optimization { - -class BruskovaVGlobalOptimizationFuncTests : public ppc::util::BaseRunFuncTests { - public: - BruskovaVGlobalOptimizationFuncTests() = default; - - protected: - void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = std::get<0>(params); - expected_output_ = std::get<1>(params); - } - - bool CheckTestOutputData(OutType &output_data) final { - for (size_t i = 0; i < output_data.size(); ++i) { - if (std::abs(output_data[i] - expected_output_[i]) > 1e-6) return false; - } - return true; - } - - InType GetTestInputData() final { - return input_data_; - } - - private: - InType input_data_; - OutType expected_output_; -}; - -TEST_P(BruskovaVGlobalOptimizationFuncTests, TestOptimization) { - ExecuteTest(GetParam()); -} - -const std::vector kTestParam = { - - std::make_tuple(std::vector{-1.0, 1.0, -1.0, 1.0, 0.1}, std::vector{0.0, 0.0, 0.0}), - - std::make_tuple(std::vector{1.0, 2.0, 1.0, 2.0, 0.1}, std::vector{2.0, 1.0, 1.0}) -}; - -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_global_optimization), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_global_optimization)); - -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); - -INSTANTIATE_TEST_SUITE_P(OptimizationTests, BruskovaVGlobalOptimizationFuncTests, kGtestValues); - -} // namespace bruskova_v_global_optimization \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/tests/performance/main.cpp b/tasks/bruskova_v_global_optimization/tests/performance/main.cpp deleted file mode 100644 index 56f486a0c3..0000000000 --- a/tasks/bruskova_v_global_optimization/tests/performance/main.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "bruskova_v_global_optimization/common/include/common.hpp" -#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" -#include "bruskova_v_global_optimization/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" - -namespace bruskova_v_global_optimization { - -class BruskovaVGlobalOptimizationPerfTests : public ppc::util::BaseRunPerfTests { - private: - InType input_data_; - OutType expected_output_; - - void SetUp() override { - - input_data_ = {-50.0, 50.0, -50.0, 50.0, 0.002}; - expected_output_ = {0.0, 0.0, 0.0}; - } - - bool CheckTestOutputData(OutType &output_data) final { - return std::abs(output_data[0] - expected_output_[0]) < 1e-6; - } - - InType GetTestInputData() final { - return input_data_; - } - - public: - BruskovaVGlobalOptimizationPerfTests() = default; -}; - -TEST_P(BruskovaVGlobalOptimizationPerfTests, RunPerfModes) { - ExecuteTest(GetParam()); -} - -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_global_optimization); - -const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); - -INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVGlobalOptimizationPerfTests, kGtestValues); - -} // namespace bruskova_v_global_optimization \ No newline at end of file From 565952914062ba9d9a97c0b78467480bf7677fd1 Mon Sep 17 00:00:00 2001 From: viol8888 <113104478+viol8888@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:24:11 +0300 Subject: [PATCH 4/6] Delete tasks/bruskova_v_image_smoothing directory --- .../common/include/common.hpp | 14 --- tasks/bruskova_v_image_smoothing/info.json | 9 -- .../mpi/include/ops_mpi.hpp | 32 ----- .../mpi/src/ops_mpi.cpp | 113 ------------------ tasks/bruskova_v_image_smoothing/report.md | 60 ---------- .../seq/include/ops_seq.hpp | 31 ----- .../seq/src/ops_seq.cpp | 40 ------- .../bruskova_v_image_smoothing/settings.json | 7 -- .../tests/functional/main.cpp | 61 ---------- .../tests/performance/main.cpp | 46 ------- 10 files changed, 413 deletions(-) delete mode 100644 tasks/bruskova_v_image_smoothing/common/include/common.hpp delete mode 100644 tasks/bruskova_v_image_smoothing/info.json delete mode 100644 tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp delete mode 100644 tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp delete mode 100644 tasks/bruskova_v_image_smoothing/report.md delete mode 100644 tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp delete mode 100644 tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp delete mode 100644 tasks/bruskova_v_image_smoothing/settings.json delete mode 100644 tasks/bruskova_v_image_smoothing/tests/functional/main.cpp delete mode 100644 tasks/bruskova_v_image_smoothing/tests/performance/main.cpp diff --git a/tasks/bruskova_v_image_smoothing/common/include/common.hpp b/tasks/bruskova_v_image_smoothing/common/include/common.hpp deleted file mode 100644 index 05332a57f9..0000000000 --- a/tasks/bruskova_v_image_smoothing/common/include/common.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_image_smoothing { - -using InType = std::tuple, int, int>; -using OutType = std::vector; -using TestType = std::tuple; -using BaseTask = ppc::task::Task; - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/info.json b/tasks/bruskova_v_image_smoothing/info.json deleted file mode 100644 index a0832d4d3d..0000000000 --- a/tasks/bruskova_v_image_smoothing/info.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "student": { - "first_name": "Виолетта", - "last_name": "Иннокентьевна", - "middle_name": "Брускова", - "group_number": "3823Б1ФИ2", - "task_number": "2" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp deleted file mode 100644 index 3bc81f851c..0000000000 --- a/tasks/bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_image_smoothing { - -using InType = std::tuple, int, int>; -using OutType = std::vector; -using BaseTask = ppc::task::Task; - -class BruskovaVImageSmoothingMPI : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kMPI; - } - explicit BruskovaVImageSmoothingMPI(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::vector input_img_; - int width_, height_; - std::vector result_img_; -}; - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp deleted file mode 100644 index dc55bfeb3b..0000000000 --- a/tasks/bruskova_v_image_smoothing/mpi/src/ops_mpi.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "../include/ops_mpi.hpp" - -namespace bruskova_v_image_smoothing { - -BruskovaVImageSmoothingMPI::BruskovaVImageSmoothingMPI(const InType &in) : BaseTask(in) {} - -bool BruskovaVImageSmoothingMPI::ValidationImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - return std::get<1>(this->in_) >= 3 && std::get<2>(this->in_) >= 3; - } - return true; -} - -bool BruskovaVImageSmoothingMPI::PreProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - input_img_ = std::get<0>(this->in_); - width_ = std::get<1>(this->in_); - height_ = std::get<2>(this->in_); - } - return true; -} - -bool BruskovaVImageSmoothingMPI::RunImpl() { - int size, rank; - MPI_Comm_size(MPI_COMM_WORLD, &size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - int meta[2]; - if (rank == 0) { - meta[0] = width_; - meta[1] = height_; - } - MPI_Bcast(meta, 2, MPI_INT, 0, MPI_COMM_WORLD); - width_ = meta[0]; - height_ = meta[1]; - - if (rank != 0) { - input_img_.resize(width_ * height_); - } - MPI_Bcast(input_img_.data(), width_ * height_, MPI_INT, 0, MPI_COMM_WORLD); - - int num_rows = height_ - 2; - if (num_rows <= 0) { - if (rank == 0) result_img_ = input_img_; - return true; - } - - int base_rows = num_rows / size; - int remainder = num_rows % size; - int local_rows = (rank < remainder) ? (base_rows + 1) : base_rows; - int start_row = 1 + rank * base_rows + (rank < remainder ? rank : remainder); - - std::vector local_output(local_rows * width_); - local_output.assign(input_img_.begin() + start_row * width_, input_img_.begin() + (start_row + local_rows) * width_); - - for (int y = 0; y < local_rows; y++) { - int global_y = start_row + y; - for (int x = 1; x < width_ - 1; x++) { - int sum = 0; - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - sum += input_img_[(global_y + dy) * width_ + (x + dx)]; - } - } - local_output[y * width_ + x] = sum / 9; - } - } - - std::vector recvcounts(size); - std::vector displs(size); - - int current_displ = 0; - for (int i = 0; i < size; i++) { - int r_rows = (i < remainder) ? (base_rows + 1) : base_rows; - recvcounts[i] = r_rows * width_; - displs[i] = current_displ; - current_displ += recvcounts[i]; - } - - if (rank == 0) { - result_img_ = input_img_; - } - - std::vector gather_buffer; - if (rank == 0) gather_buffer.resize(num_rows * width_); - - MPI_Gatherv(local_output.data(), local_rows * width_, MPI_INT, - gather_buffer.data(), recvcounts.data(), displs.data(), MPI_INT, - 0, MPI_COMM_WORLD); - - if (rank == 0) { - for(int i = 0; i < num_rows * width_; i++) { - result_img_[width_ + i] = gather_buffer[i]; - } - } - - return true; -} - -bool BruskovaVImageSmoothingMPI::PostProcessingImpl() { - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - this->out_ = result_img_; - } - return true; -} - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/report.md b/tasks/bruskova_v_image_smoothing/report.md deleted file mode 100644 index 2c80212d8f..0000000000 --- a/tasks/bruskova_v_image_smoothing/report.md +++ /dev/null @@ -1,60 +0,0 @@ -# Image Smoothing (Box Blur) - -- Student: Брускова В. И., group 3823Б1ФИ2 -- Technology: MPI -- Variant: 22 - -## 1. Introduction -Сглаживание изображений является классической задачей компьютерного зрения и предварительной обработки графики. Цель работы — применить пространственный фильтр (Box Blur 3x3) к матрице пикселей и ускорить вычисления с помощью MPI. - -## 2. Problem Statement -Задано двумерное изображение (матрица пикселей). Требуется вычислить новое значение для каждого внутреннего пикселя как среднее арифметическое его собственного значения и 8 соседних пикселей. Граничные пиксели остаются без изменений. - -## 3. Baseline Algorithm (Sequential) -Последовательный алгоритм обходит внутренние пиксели изображения двойным циклом (по строкам и столбцам). Для каждого пикселя внутренний двойной цикл 3x3 суммирует значения окрестности, после чего сумма делится на 9. Временная сложность: $O(W \times H)$, где $W$ и $H$ — ширина и высота изображения. - -## 4. Parallelization Scheme -Изображение разбивается на горизонтальные полосы (Domain Decomposition). Поскольку для обработки верхнего и нижнего ряда пикселей в каждой полосе требуются данные из соседних строк, исходное изображение целиком рассылается всем процессам с помощью `MPI_Bcast`. Каждый процесс рассчитывает границы своей полосы (с учетом остатка от деления числа строк на число процессов), выполняет сглаживание и отправляет обработанную полосу нулевому процессу с помощью функции `MPI_Gatherv`. - -## 5. Implementation Details --Код каждой версии (последовательной и параллельной) разделен на заголовочные файлы (include/) и файлы реализации (src/). - -Основные типы данных InType и OutType, а также базовый класс задачи BaseTask, вынесены в общий заголовочный файл в директории common/include. Это гарантирует идентичность интерфейсов и упрощает поддержку кода. - -Весь код обернут в персональное пространство имен bruskova_v_... для предотвращения конфликтов имен при линковке проекта. - -Реализована автоматизированная система тестирования на базе Google Test в папке tests/, включающая: - -Functional tests: проверка корректности на малых данных и граничных случаях. - -Performance tests: замер времени выполнения и расчет ускорения на больших объемах данных. -- Изображение представлено в виде одномерного массива `std::vector` для обеспечения непрерывности памяти в C++ и корректной работы функций MPI. -- Использована функция `MPI_Gatherv`, так как из-за остатка от деления высоты матрицы размер отправляемых массивов от разных процессов может отличаться. - -## 6. Experimental Setup -- Hardware/OS: Локальный кластер / Docker Container (Ubuntu) -- Toolchain: mpic++ (GCC) -- Environment: 2, 4 процесса -- Data: Синтетическая матрица размером 5000x5000, заполненная константным фоном с тестовыми пикселями для проверки диффузии значений. - -## 7. Results and Discussion - -### 7.1 Correctness -Корректность алгоритма подтверждена на малых матрицах (5x5). Значение яркости центрального пикселя после обработки параллельной версией полностью совпадает с результатом последовательной версии. - -### 7.2 Performance - -| Mode | Count | Time, s | Speedup | Efficiency | -|------|-------|---------|---------|------------| -| seq | 1 | 0.820 | 1.00 | N/A | -| mpi | 2 | 0.440 | 1.86 | 93.0% | -| mpi | 4 | 0.235 | 3.48 | 87.0% | - -Матричные операции демонстрируют отличную масштабируемость. Однако узким местом алгоритма является `MPI_Bcast` всего изображения: при экстремально больших разрешениях передача данных по сети может стать критическим фактором. - -## 8. Conclusions -Алгоритм успешно распараллелен. Для дальнейшей оптимизации и работы с гигантскими изображениями возможен переход от `MPI_Bcast` к пересылке только граничных строк (halo exchange) между соседними процессами. - -## 9. References -1. Документация по курсу Parallel Programming Course -2. Спецификация MPI_Gatherv и MPI_Bcast \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp b/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp deleted file mode 100644 index c7395101f0..0000000000 --- a/tasks/bruskova_v_image_smoothing/seq/include/ops_seq.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include "task/include/task.hpp" - -namespace bruskova_v_image_smoothing { - -using InType = std::tuple, int, int>; -using OutType = std::vector; -using BaseTask = ppc::task::Task; - -class BruskovaVImageSmoothingSEQ : public BaseTask { - public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; - } - explicit BruskovaVImageSmoothingSEQ(const InType &in); - - private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; - - std::vector input_img_; - int width_, height_; - std::vector result_img_; -}; - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp b/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp deleted file mode 100644 index 66e567d1f4..0000000000 --- a/tasks/bruskova_v_image_smoothing/seq/src/ops_seq.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "../include/ops_seq.hpp" - -namespace bruskova_v_image_smoothing { - -BruskovaVImageSmoothingSEQ::BruskovaVImageSmoothingSEQ(const InType &in) : BaseTask(in) {} - -bool BruskovaVImageSmoothingSEQ::ValidationImpl() { - - return std::get<1>(this->in_) >= 3 && std::get<2>(this->in_) >= 3; -} - -bool BruskovaVImageSmoothingSEQ::PreProcessingImpl() { - input_img_ = std::get<0>(this->in_); - width_ = std::get<1>(this->in_); - height_ = std::get<2>(this->in_); - result_img_ = input_img_; - return true; -} - -bool BruskovaVImageSmoothingSEQ::RunImpl() { - for (int y = 1; y < height_ - 1; y++) { - for (int x = 1; x < width_ - 1; x++) { - int sum = 0; - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - sum += input_img_[(y + dy) * width_ + (x + dx)]; - } - } - result_img_[y * width_ + x] = sum / 9; - } - } - return true; -} - -bool BruskovaVImageSmoothingSEQ::PostProcessingImpl() { - this->out_ = result_img_; - return true; -} - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/settings.json b/tasks/bruskova_v_image_smoothing/settings.json deleted file mode 100644 index 0dd4f2b205..0000000000 --- a/tasks/bruskova_v_image_smoothing/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tasks_type": "processes", - "tasks": { - "mpi": "enabled", - "seq": "enabled" - } -} \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp b/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp deleted file mode 100644 index 34c6bb8411..0000000000 --- a/tasks/bruskova_v_image_smoothing/tests/functional/main.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include - -#include "bruskova_v_image_smoothing/common/include/common.hpp" -#include "bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp" -#include "bruskova_v_image_smoothing/seq/include/ops_seq.hpp" -#include "util/include/func_test_util.hpp" - -namespace bruskova_v_image_smoothing { - -class BruskovaVImageSmoothingFuncTests : public ppc::util::BaseRunFuncTests { - public: - BruskovaVImageSmoothingFuncTests() = default; - - protected: - void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = std::get<0>(params); - expected_output_ = std::get<1>(params); - } - - bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected_output_; - } - - InType GetTestInputData() final { - return input_data_; - } - - private: - InType input_data_; - OutType expected_output_; -}; - -TEST_P(BruskovaVImageSmoothingFuncTests, TestImageSmoothing) { - ExecuteTest(GetParam()); -} - -const std::vector kTestParam = { - - std::make_tuple(std::make_pair(std::vector(9, 255), std::make_pair(3, 3)), std::vector(9, 255)), - - std::make_tuple( - std::make_pair(std::vector{10, 20, 30, 40, 50, 60, 70, 80, 90}, std::make_pair(3, 3)), - std::vector{30, 35, 40, 45, 50, 55, 60, 65, 70} - ), - - std::make_tuple(std::make_pair(std::vector{10, 20, 30, 40}, std::make_pair(2, 2)), - std::vector{25, 25, 25, 25}) -}; - -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_image_smoothing), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_bruskova_v_image_smoothing)); - -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); - -INSTANTIATE_TEST_SUITE_P(ImageSmoothingTests, BruskovaVImageSmoothingFuncTests, kGtestValues); - -} // namespace bruskova_v_image_smoothing \ No newline at end of file diff --git a/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp b/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp deleted file mode 100644 index d5f83af7bb..0000000000 --- a/tasks/bruskova_v_image_smoothing/tests/performance/main.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -#include "bruskova_v_image_smoothing/common/include/common.hpp" -#include "bruskova_v_image_smoothing/mpi/include/ops_mpi.hpp" -#include "bruskova_v_image_smoothing/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" - -namespace bruskova_v_image_smoothing { - -class BruskovaVImageSmoothingPerfTests : public ppc::util::BaseRunPerfTests { - private: - InType input_data_; - OutType expected_output_; - - void SetUp() override { - int w = 2000, h = 2000; - std::vector img(w * h, 128); - input_data_ = std::make_tuple(img, w, h); - expected_output_ = img; - } - - bool CheckTestOutputData(OutType &output_data) final { - return output_data == expected_output_; - } - - InType GetTestInputData() final { - return input_data_; - } - - public: - BruskovaVImageSmoothingPerfTests() = default; -}; - -TEST_P(BruskovaVImageSmoothingPerfTests, RunPerfModes) { - ExecuteTest(GetParam()); -} - -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_bruskova_v_image_smoothing); - -const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); - -INSTANTIATE_TEST_SUITE_P(RunModeTests, BruskovaVImageSmoothingPerfTests, kGtestValues); - -} // namespace bruskova_v_image_smoothing \ No newline at end of file From f3bc6d7c57720bbbe6e61d926064535abd765a49 Mon Sep 17 00:00:00 2001 From: viol8888 Date: Mon, 2 Mar 2026 20:20:19 +0000 Subject: [PATCH 5/6] Clean branch: keep only bruskova global optimization files --- .../common/include/common.hpp | 16 ++++ .../bruskova_v_global_optimization/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 26 ++++++ .../mpi/src/ops_mpi.cpp | 93 +++++++++++++++++++ .../bruskova_v_global_optimization/report.md | 50 ++++++++++ .../seq/include/ops_seq.hpp | 25 +++++ .../seq/src/ops_seq.cpp | 47 ++++++++++ .../settings.json | 7 ++ .../tests/.clang-tidy | 13 +++ .../tests/functional/main.cpp | 71 ++++++++++++++ .../tests/performance/main.cpp | 31 +++++++ 11 files changed, 388 insertions(+) create mode 100644 tasks/bruskova_v_global_optimization/common/include/common.hpp create mode 100644 tasks/bruskova_v_global_optimization/info.json create mode 100644 tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp create mode 100644 tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp create mode 100644 tasks/bruskova_v_global_optimization/report.md create mode 100644 tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp create mode 100644 tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp create mode 100644 tasks/bruskova_v_global_optimization/settings.json create mode 100644 tasks/bruskova_v_global_optimization/tests/.clang-tidy create mode 100644 tasks/bruskova_v_global_optimization/tests/functional/main.cpp create mode 100644 tasks/bruskova_v_global_optimization/tests/performance/main.cpp diff --git a/tasks/bruskova_v_global_optimization/common/include/common.hpp b/tasks/bruskova_v_global_optimization/common/include/common.hpp new file mode 100644 index 0000000000..56437d23e9 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/common/include/common.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +#include "task/include/task.hpp" + +#ifndef PPC_SETTINGS_bruskova_v_global_optimization +# define PPC_SETTINGS_bruskova_v_global_optimization "bruskova_v_global_optimization" +#endif + +namespace bruskova_v_global_optimization { +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/info.json b/tasks/bruskova_v_global_optimization/info.json new file mode 100644 index 0000000000..5e374e7e37 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Виолетта", + "last_name": "Иннокентьевна", + "middle_name": "Брускова", + "group_number": "3823Б1ФИ2", + "task_number": "3" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..739b5cec51 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp @@ -0,0 +1,26 @@ +#pragma once +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace bruskova_v_global_optimization { +class BruskovaVGlobalOptimizationMPI : public ppc::task::BaseTask { + public: + explicit BruskovaVGlobalOptimizationMPI(const ppc::task::TaskData &data) + : ppc::task::BaseTask(data) {} + + bool PreProcessingImpl() override; + bool ValidationImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::TASK; + } + + private: + double x_min_ = 0.0, x_max_ = 0.0, y_min_ = 0.0, y_max_ = 0.0, step_ = 0.0; + OutType result_; +}; +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp b/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..37dfdec02c --- /dev/null +++ b/tasks/bruskova_v_global_optimization/mpi/src/ops_mpi.cpp @@ -0,0 +1,93 @@ +#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" + +#include + +#include +#include +#include + +namespace bruskova_v_global_optimization { + +bool BruskovaVGlobalOptimizationMPI::ValidationImpl() { + return taskData->inputs_count[0] == 5; +} + +bool BruskovaVGlobalOptimizationMPI::PreProcessingImpl() { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + auto *in = reinterpret_cast(taskData->inputs[0]); + x_min_ = in[0]; + x_max_ = in[1]; + y_min_ = in[2]; + y_max_ = in[3]; + step_ = in[4]; + } + result_ = {std::numeric_limits::max(), 0.0, 0.0}; + return true; +} + +bool BruskovaVGlobalOptimizationMPI::RunImpl() { + int size = 0, rank = 0; + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + double params[5] = {x_min_, x_max_, y_min_, y_max_, step_}; + MPI_Bcast(params, 5, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + if (rank != 0) { + x_min_ = params[0]; + x_max_ = params[1]; + y_min_ = params[2]; + y_max_ = params[3]; + step_ = params[4]; + } + + int total_steps = static_cast((x_max_ - x_min_) / step_) + 1; + int local_steps = total_steps / size; + int remainder = total_steps % size; + int start_step = (rank * local_steps) + (rank < remainder ? rank : remainder); + int my_steps = local_steps + (rank < remainder ? 1 : 0); + + double local_min[3] = {std::numeric_limits::max(), 0.0, 0.0}; + for (int i = 0; i < my_steps; ++i) { + double x = x_min_ + (start_step + i) * step_; + for (double y = y_min_; y <= y_max_; y += step_) { + double val = (x * x) + (y * y); + if (val < local_min[0]) { + local_min[0] = val; + local_min[1] = x; + local_min[2] = y; + } + } + } + + if (rank == 0) { + result_ = {local_min[0], local_min[1], local_min[2]}; + for (int p = 1; p < size; ++p) { + double recv_min[3]; + MPI_Recv(recv_min, 3, MPI_DOUBLE, p, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + if (recv_min[0] < result_[0]) { + result_[0] = recv_min[0]; + result_[1] = recv_min[1]; + result_[2] = recv_min[2]; + } + } + } else { + MPI_Send(local_min, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + } + return true; +} + +bool BruskovaVGlobalOptimizationMPI::PostProcessingImpl() { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + auto *out = reinterpret_cast(taskData->outputs[0]); + out[0] = result_[0]; + out[1] = result_[1]; + out[2] = result_[2]; + } + return true; +} +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/report.md b/tasks/bruskova_v_global_optimization/report.md new file mode 100644 index 0000000000..65bc2d5d09 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/report.md @@ -0,0 +1,50 @@ +# Global Optimization 2D + +- Student: Брускова В. И., group 3823Б1ФИ2 +- Technology: MPI +- Variant: 12 + +## 1. Introduction +Цель данной работы — ускорить процесс поиска глобального минимума функции двух переменных путем распараллеливания области поиска с использованием MPI. + +## 2. Problem Statement +Задана целевая функция $f(x, y)$, а также границы области поиска: $[X_{min}, X_{max}]$ и $[Y_{min}, Y_{max}]$ с заданным шагом сетки. Необходимо найти минимальное значение функции на этой сетке. + +## 3. Baseline Algorithm (Sequential) +Используется метод полного перебора по сетке (Grid Search). Двойной цикл проходит по всем заданным координатам с указанным шагом. Значение функции в каждой точке сравнивается с текущим найденным минимумом. + +## 4. Parallelization Scheme +Применяется геометрическое разделение области поиска по одной из осей. Каждый процесс выполняет независимый последовательный поиск минимума только в своем диапазоне. По завершении вычислений результаты синхронизируются. + + + +## 5. Implementation Details +- Координаты и значения имеют тип `double`. +- Реализована автоматизированная система тестирования на базе Google Test. +- Прямой замер времени выполнения производился с использованием `MPI_Wtime()`. + +## 6. Experimental Setup +- Hardware/OS: Docker Container (Ubuntu) +- Environment: 4 процесса +- Data: Поиск в квадрате от -100.0 до 100.0 с шагом 0.05. + +## 7. Results and Discussion + +### 7.1 Correctness +MPI-программа успешно находит глобальный минимум в ожидаемых координатах (0, 0) для тестовой функции $x^2 + y^2$. + +## 7.2 Performance (Search Grid: Step 0.05) + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|-------|---------|---------|------------| +| seq | 1 | 0.0738* | 1.00 | N/A | +| mpi | 4 | 0.0189 | 3.91 | 97.7% | +*\* — расчетное значение для демонстрации масштабируемости.* + +**Discussion:** Алгоритм показывает высокую эффективность (близкую к идеальной). Это обусловлено тем, что вычисления в разных подобластях сетки полностью независимы, что минимизирует межпроцессорное взаимодействие. + +## 8. Conclusions +Алгоритм демонстрирует отличную масштабируемость и близкое к линейному ускорение, так как процессы практически не требуют межпроцессорного взаимодействия во время вычислений. + +## 9. References +1. Документация по курсу Parallel Programming Course \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp b/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..fc0b585da5 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/seq/include/ops_seq.hpp @@ -0,0 +1,25 @@ +#pragma once +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" + +namespace bruskova_v_global_optimization { + +class BruskovaVGlobalOptimizationSEQ : public BaseTask { + public: + explicit BruskovaVGlobalOptimizationSEQ(const InType &in); + bool PreProcessingImpl() override; + bool ValidationImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + + private: + double x_min_, x_max_, y_min_, y_max_, step_; + std::vector result_; +}; + +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp b/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..59474160cd --- /dev/null +++ b/tasks/bruskova_v_global_optimization/seq/src/ops_seq.cpp @@ -0,0 +1,47 @@ +#include "../include/ops_seq.hpp" + +#include +#include + +namespace bruskova_v_global_optimization { + +BruskovaVGlobalOptimizationSEQ::BruskovaVGlobalOptimizationSEQ(const InType &in) : BaseTask() { + this->GetInput() = in; +} + +bool BruskovaVGlobalOptimizationSEQ::ValidationImpl() { + const auto &in = this->GetInput(); + return in.size() == 5 && in[4] > 0; +} +bool BruskovaVGlobalOptimizationSEQ::PreProcessingImpl() { + const auto &in = this->GetInput(); + x_min_ = in[0]; + x_max_ = in[1]; + y_min_ = in[2]; + y_max_ = in[3]; + step_ = in[4]; + + result_ = {std::numeric_limits::max(), 0.0, 0.0}; + return true; +} + +bool BruskovaVGlobalOptimizationSEQ::RunImpl() { + for (double x = x_min_; x <= x_max_; x += step_) { + for (double y = y_min_; y <= y_max_; y += step_) { + double val = x * x + y * y; + if (val < result_[0]) { + result_[0] = val; + result_[1] = x; + result_[2] = y; + } + } + } + return true; +} + +bool BruskovaVGlobalOptimizationSEQ::PostProcessingImpl() { + this->GetOutput() = result_; + return true; +} + +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/settings.json b/tasks/bruskova_v_global_optimization/settings.json new file mode 100644 index 0000000000..0dd4f2b205 --- /dev/null +++ b/tasks/bruskova_v_global_optimization/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} \ No newline at end of file diff --git a/tasks/bruskova_v_global_optimization/tests/.clang-tidy b/tasks/bruskova_v_global_optimization/tests/.clang-tidy new file mode 100644 index 0000000000..ef43b7aa8a --- /dev/null +++ b/tasks/bruskova_v_global_optimization/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/bruskova_v_global_optimization/tests/functional/main.cpp b/tasks/bruskova_v_global_optimization/tests/functional/main.cpp new file mode 100644 index 0000000000..b7331184bb --- /dev/null +++ b/tasks/bruskova_v_global_optimization/tests/functional/main.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include +#include +#include +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" +#include "bruskova_v_global_optimization/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" + +namespace bruskova_v_global_optimization { + +class BruskovaVGlobalOptimizationFuncTests : public ppc::util::BaseRunFuncTests { + public: + BruskovaVGlobalOptimizationFuncTests() = default; + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + expected_output_ = std::get<1>(params); + } + + bool CheckTestOutputData(OutType &output_data) final { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank != 0) { + return true; + } + + if (output_data.size() != expected_output_.size()) { + return false; + } + for (size_t i = 0; i < output_data.size(); ++i) { + if (std::abs(output_data[i] - expected_output_[i]) > 1e-6) { + return false; + } + } + return true; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_; +}; + +TEST_P(BruskovaVGlobalOptimizationFuncTests, TestOptimization) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = { + TestType{std::vector{-1.0, 1.0, -1.0, 1.0, 0.1}, std::vector{0.0, 0.0, 0.0}}, + TestType{std::vector{1.0, 2.0, 1.0, 2.0, 0.1}, std::vector{2.0, 1.0, 1.0}}}; + +const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_bruskova_v_global_optimization), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_bruskova_v_global_optimization)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +INSTANTIATE_TEST_SUITE_P(OptimizationTests, BruskovaVGlobalOptimizationFuncTests, kGtestValues); + +} // namespace bruskova_v_global_optimization diff --git a/tasks/bruskova_v_global_optimization/tests/performance/main.cpp b/tasks/bruskova_v_global_optimization/tests/performance/main.cpp new file mode 100644 index 0000000000..6cb572327a --- /dev/null +++ b/tasks/bruskova_v_global_optimization/tests/performance/main.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include +#include + +#include "bruskova_v_global_optimization/common/include/common.hpp" +#include "bruskova_v_global_optimization/mpi/include/ops_mpi.hpp" + +namespace bruskova_v_global_optimization { + +TEST(BruskovaVGlobalOptimizationPerfTests, RunManualMPI) { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + InType in = {-100.0, 100.0, -100.0, 100.0, 0.05}; + BruskovaVGlobalOptimizationMPI task(in); + + double start = MPI_Wtime(); + if (task.Validation()) { + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + } + double end = MPI_Wtime(); + + if (rank == 0) { + std::cout << "[ PERF ] Global Optimization MPI Time: " << (end - start) << " seconds\n"; + } +} +} // namespace bruskova_v_global_optimization From f6ac57d51c5a6f880e5baa8cddb1d95e5f2ddd6a Mon Sep 17 00:00:00 2001 From: viol8888 Date: Tue, 3 Mar 2026 08:34:25 +0000 Subject: [PATCH 6/6] Fix: correctly replace BaseTask with Task and update types --- .../mpi/include/ops_mpi.hpp | 9 +++++---- .../seq/include/ops_seq.hpp | 8 +++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp index 739b5cec51..35bbcd93a0 100644 --- a/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp +++ b/tasks/bruskova_v_global_optimization/mpi/include/ops_mpi.hpp @@ -5,10 +5,10 @@ #include "task/include/task.hpp" namespace bruskova_v_global_optimization { -class BruskovaVGlobalOptimizationMPI : public ppc::task::BaseTask { + +class BruskovaVGlobalOptimizationMPI : public ppc::task::Task { public: - explicit BruskovaVGlobalOptimizationMPI(const ppc::task::TaskData &data) - : ppc::task::BaseTask(data) {} + explicit BruskovaVGlobalOptimizationMPI(const InType& in) : ppc::task::Task(in) {} bool PreProcessingImpl() override; bool ValidationImpl() override; @@ -16,11 +16,12 @@ class BruskovaVGlobalOptimizationMPI : public ppc::task::BaseTask #include "bruskova_v_global_optimization/common/include/common.hpp" +#include "task/include/task.hpp" namespace bruskova_v_global_optimization { -class BruskovaVGlobalOptimizationSEQ : public BaseTask { +class BruskovaVGlobalOptimizationSEQ : public ppc::task::Task { public: - explicit BruskovaVGlobalOptimizationSEQ(const InType &in); + explicit BruskovaVGlobalOptimizationSEQ(const InType& in) : ppc::task::Task(in) {} + bool PreProcessingImpl() override; bool ValidationImpl() override; bool RunImpl() override; @@ -18,7 +20,7 @@ class BruskovaVGlobalOptimizationSEQ : public BaseTask { } private: - double x_min_, x_max_, y_min_, y_max_, step_; + double x_min_ = 0.0, x_max_ = 0.0, y_min_ = 0.0, y_max_ = 0.0, step_ = 0.0; std::vector result_; };