From 6d473efa50e4b3634faacb124ffbf0b9d8983f3e Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Mon, 17 Nov 2025 01:21:55 +0300 Subject: [PATCH 01/27] Initial commit --- .../common/include/common.hpp | 15 +++ .../data/pic.jpg | Bin 0 -> 23 bytes .../info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 22 +++++ .../mpi/src/ops_mpi.cpp | 72 +++++++++++++++ .../report.md | 0 .../seq/include/ops_seq.hpp | 22 +++++ .../seq/src/ops_seq.cpp | 60 ++++++++++++ .../settings.json | 7 ++ .../tests/.clang-tidy | 13 +++ .../tests/functional/main.cpp | 86 ++++++++++++++++++ .../tests/performance/main.cpp | 40 ++++++++ 12 files changed, 346 insertions(+) create mode 100644 tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg create mode 100644 tasks/egorova_l_find_max_val_col_matrix/info.json create mode 100644 tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/report.md create mode 100644 tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/settings.json create mode 100644 tasks/egorova_l_find_max_val_col_matrix/tests/.clang-tidy create mode 100644 tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp create mode 100644 tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp diff --git a/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp new file mode 100644 index 000000000..85504b33f --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +using InType = int; +using OutType = int; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg b/tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..637624238c89d914613ed301968bffbf462bc110 GIT binary patch literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY + +#include +#include + +#include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { + auto input = GetInput(); + if (input == 0) { + return false; + } + + for (InType i = 0; i < GetInput(); i++) { + for (InType j = 0; j < GetInput(); j++) { + for (InType k = 0; k < GetInput(); k++) { + std::vector tmp(i + j + k, 1); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); + GetOutput() -= i + j + k; + } + } + } + + const int num_threads = ppc::util::GetNumThreads(); + GetOutput() *= num_threads; + + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + GetOutput() /= num_threads; + } else { + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + + if (counter != 0) { + GetOutput() /= counter; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + return GetOutput() > 0; +} + +bool EgorovaLFindMaxValColMatrixMPI::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/report.md b/tasks/egorova_l_find_max_val_col_matrix/report.md new file mode 100644 index 000000000..e69de29bb diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp new file mode 100644 index 000000000..bec18f5ec --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +class EgorovaLFindMaxValColMatrixSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit EgorovaLFindMaxValColMatrixSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp new file mode 100644 index 000000000..54d74a7ed --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -0,0 +1,60 @@ +#include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" + +#include +#include + +#include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { + if (GetInput() == 0) { + return false; + } + + for (InType i = 0; i < GetInput(); i++) { + for (InType j = 0; j < GetInput(); j++) { + for (InType k = 0; k < GetInput(); k++) { + std::vector tmp(i + j + k, 1); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); + GetOutput() -= i + j + k; + } + } + } + + const int num_threads = ppc::util::GetNumThreads(); + GetOutput() *= num_threads; + + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + + if (counter != 0) { + GetOutput() /= counter; + } + return GetOutput() > 0; +} + +bool EgorovaLFindMaxValColMatrixSEQ::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/settings.json b/tasks/egorova_l_find_max_val_col_matrix/settings.json new file mode 100644 index 000000000..b1a0d5257 --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/.clang-tidy b/tasks/egorova_l_find_max_val_col_matrix/tests/.clang-tidy new file mode 100644 index 000000000..ef43b7aa8 --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/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/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp new file mode 100644 index 000000000..f5e31beab --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -0,0 +1,86 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" +#include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" +#include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); + } + + protected: + void SetUp() override { + int width = -1; + int height = -1; + int channels = -1; + std::vector img; + // Read image in RGB to ensure consistent channel count + { + std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_example_processes, "pic.jpg"); + auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); + if (data == nullptr) { + throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + } + channels = STBI_rgb; + img = std::vector(data, data + (static_cast(width * height * channels))); + stbi_image_free(data); + if (std::cmp_not_equal(width, height)) { + throw std::runtime_error("width != height: "); + } + } + + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + } + + bool CheckTestOutputData(OutType &output_data) final { + return (input_data_ == output_data); + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_ = 0; +}; + +namespace { + +TEST_P(EgorovaLRunFuncTestsProcesses, MatmulFromPic) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = EgorovaLRunFuncTestsProcesses::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(PicMatrixTests, EgorovaLRunFuncTestsProcesses, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp new file mode 100644 index 000000000..b017ae50b --- /dev/null +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -0,0 +1,40 @@ +#include + +#include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" +#include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" +#include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace egorova_l_find_max_val_col_matrix { + +class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { + const int kCount_ = 100; + InType input_data_{}; + + void SetUp() override { + input_data_ = kCount_; + } + + bool CheckTestOutputData(OutType &output_data) final { + return input_data_ == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(EgorovaLRunPerfTestProcesses, EgorovaLRunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_example_processes); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = EgorovaLRunPerfTestProcesses::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(EgorovaLRunModeTests, EgorovaLRunPerfTestProcesses, kGtestValues, kPerfTestName); + +} // namespace egorova_l_find_max_val_col_matrix From 5050cedf6701936576216f4e26b0cc2cca8aea1e Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Mon, 17 Nov 2025 02:14:17 +0300 Subject: [PATCH 02/27] 1 --- .../tests/functional/main.cpp | 6 +++--- .../tests/performance/main.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index f5e31beab..6050428e1 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -71,9 +71,9 @@ TEST_P(EgorovaLRunFuncTestsProcesses, MatmulFromPic) { const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes)); +const auto kTestTasksList = std::tuple_cat( + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp index b017ae50b..de89119df 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -29,7 +29,8 @@ TEST_P(EgorovaLRunPerfTestProcesses, EgorovaLRunPerfModes) { } const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_example_processes); + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_example_processes); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); From 05d696ee66503e29e3a722ea7cc1d6b512df7d37 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 09:24:13 +0000 Subject: [PATCH 03/27] 2 --- .../common/include/common.hpp | 5 +- .../info.json | 18 +-- .../mpi/src/ops_mpi.cpp | 119 +++++++++++++----- .../seq/src/ops_seq.cpp | 62 +++++---- .../settings.json | 14 +-- .../tests/functional/main.cpp | 99 ++++++++++----- .../tests/performance/main.cpp | 41 +++++- 7 files changed, 252 insertions(+), 106 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp index 85504b33f..667139118 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp @@ -2,13 +2,14 @@ #include #include +#include #include "task/include/task.hpp" namespace egorova_l_find_max_val_col_matrix { -using InType = int; -using OutType = int; +using InType = std::vector>; +using OutType = std::vector; using TestType = std::tuple; using BaseTask = ppc::task::Task; diff --git a/tasks/egorova_l_find_max_val_col_matrix/info.json b/tasks/egorova_l_find_max_val_col_matrix/info.json index de9442bb9..2e5f4aa98 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/info.json +++ b/tasks/egorova_l_find_max_val_col_matrix/info.json @@ -1,9 +1,9 @@ -{ - "student": { - "first_name": "first_name_p", - "last_name": "last_name_p", - "middle_name": "middle_name_p", - "group_number": "2222222_p", - "task_number": "1" - } -} +{ + "student": { + "first_name": "first_name_p", + "last_name": "last_name_p", + "middle_name": "middle_name_p", + "group_number": "2222222_p", + "task_number": "1" + } +} diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 3595670cc..f5039f1ae 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -2,7 +2,8 @@ #include -#include +#include +#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" @@ -13,60 +14,118 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = 0; + GetOutput() = std::vector(); } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + if (GetInput().empty()) { + return true; + } + + size_t cols = GetInput()[0].size(); + for (const auto &row : GetInput()) { + if (row.size() != cols) { + return false; + } + } + + return GetOutput().empty(); } bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + return true; } bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { - auto input = GetInput(); - if (input == 0) { - return false; + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + // Определяем, пустая ли матрица + int is_empty = 0; + if (rank == 0) { + is_empty = GetInput().empty() ? 1 : 0; } + MPI_Bcast(&is_empty, 1, MPI_INT, 0, MPI_COMM_WORLD); - for (InType i = 0; i < GetInput(); i++) { - for (InType j = 0; j < GetInput(); j++) { - for (InType k = 0; k < GetInput(); k++) { - std::vector tmp(i + j + k, 1); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); - GetOutput() -= i + j + k; - } - } + if (is_empty) { + GetOutput() = std::vector(); + MPI_Barrier(MPI_COMM_WORLD); + return true; } - const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; + // Бродкастим размеры матрицы + int rows = 0, cols = 0; + if (rank == 0) { + rows = static_cast(GetInput().size()); + cols = static_cast(GetInput()[0].size()); + } - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); + // Создаем и бродкастим плоскую матрицу + std::vector flat_matrix(rows * cols); if (rank == 0) { - GetOutput() /= num_threads; - } else { - int counter = 0; - for (int i = 0; i < num_threads; i++) { - counter++; + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + flat_matrix[i * cols + j] = GetInput()[i][j]; + } } + } + MPI_Bcast(flat_matrix.data(), rows * cols, MPI_INT, 0, MPI_COMM_WORLD); + + // Распределяем столбцы между процессами + int cols_per_proc = cols / size; + int remainder = cols % size; + + // Определяем диапазон столбцов для текущего процесса + int start_col, local_cols_count; + if (rank < remainder) { + start_col = rank * (cols_per_proc + 1); + local_cols_count = cols_per_proc + 1; + } else { + start_col = remainder * (cols_per_proc + 1) + (rank - remainder) * cols_per_proc; + local_cols_count = cols_per_proc; + } + + // Каждый процесс вычисляет максимумы ТОЛЬКО для своих столбцов + std::vector local_max(local_cols_count, std::numeric_limits::min()); - if (counter != 0) { - GetOutput() /= counter; + for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { + int global_col = start_col + local_idx; + for (int row = 0; row < rows; ++row) { + int value = flat_matrix[row * cols + global_col]; + if (value > local_max[local_idx]) { + local_max[local_idx] = value; + } } } + // Подготавливаем массивы для сбора результатов + std::vector all_max(cols, std::numeric_limits::min()); + std::vector recv_counts(size); + std::vector displs(size); + + // Определяем сколько столбцов у каждого процесса + for (int i = 0; i < size; ++i) { + recv_counts[i] = (i < remainder) ? (cols_per_proc + 1) : cols_per_proc; + displs[i] = (i == 0) ? 0 : displs[i - 1] + recv_counts[i - 1]; + } + + // Собираем результаты от всех процессов + MPI_Allgatherv(local_max.data(), local_cols_count, MPI_INT, all_max.data(), recv_counts.data(), displs.data(), + MPI_INT, MPI_COMM_WORLD); + + // Все процессы получают полный результат + GetOutput() = all_max; + MPI_Barrier(MPI_COMM_WORLD); - return GetOutput() > 0; + return true; } bool EgorovaLFindMaxValColMatrixMPI::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + return true; } } // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index 54d74a7ed..a9a27f751 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -1,6 +1,7 @@ #include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" -#include +#include +#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" @@ -11,50 +12,57 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = 0; + GetOutput() = std::vector(); } bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + // Разрешаем пустую матрицу + if (GetInput().empty()) { + return true; + } + + // Проверяем, что все строки имеют одинаковую длину + size_t cols = GetInput()[0].size(); + for (const auto &row : GetInput()) { + if (row.size() != cols) { + return false; + } + } + + return GetOutput().empty(); } bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + return true; } bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { - if (GetInput() == 0) { - return false; - } + const auto &matrix = GetInput(); - for (InType i = 0; i < GetInput(); i++) { - for (InType j = 0; j < GetInput(); j++) { - for (InType k = 0; k < GetInput(); k++) { - std::vector tmp(i + j + k, 1); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); - GetOutput() -= i + j + k; - } - } + // Обрабатываем пустую матрицу + if (matrix.empty()) { + GetOutput() = std::vector(); + return true; } - const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; + size_t rows = matrix.size(); + size_t cols = matrix[0].size(); + std::vector result(cols, std::numeric_limits::min()); - int counter = 0; - for (int i = 0; i < num_threads; i++) { - counter++; + for (size_t j = 0; j < cols; ++j) { + for (size_t i = 0; i < rows; ++i) { + if (matrix[i][j] > result[j]) { + result[j] = matrix[i][j]; + } + } } - if (counter != 0) { - GetOutput() /= counter; - } - return GetOutput() > 0; + GetOutput() = result; + return true; } bool EgorovaLFindMaxValColMatrixSEQ::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + return true; } } // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/settings.json b/tasks/egorova_l_find_max_val_col_matrix/settings.json index b1a0d5257..7d2c35b29 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/settings.json +++ b/tasks/egorova_l_find_max_val_col_matrix/settings.json @@ -1,7 +1,7 @@ -{ - "tasks_type": "processes", - "tasks": { - "mpi": "enabled", - "seq": "enabled" - } -} +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 6050428e1..20fa98908 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -1,15 +1,12 @@ #include -#include #include #include #include -#include -#include -#include +#include +#include #include #include -#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" @@ -28,31 +25,74 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests img; - // Read image in RGB to ensure consistent channel count - { - std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_example_processes, "pic.jpg"); - auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); - if (data == nullptr) { - throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + auto test_params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + int test_type = std::get<0>(test_params); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(10, 50); // Уменьшим диапазон + + switch (test_type) { + case 0: { // Пустая матрица + input_data_ = {}; + break; + } + case 1: { // Большая матрица (4x4) + input_data_ = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; + break; + } + case 2: { // 1 столбец + input_data_ = {{1}, {5}, {3}, {7}}; + break; + } + case 3: { // Неквадратная матрица (3x2) + input_data_ = {{1, 2}, {3, 4}, {5, 6}}; + break; } - channels = STBI_rgb; - img = std::vector(data, data + (static_cast(width * height * channels))); - stbi_image_free(data); - if (std::cmp_not_equal(width, height)) { - throw std::runtime_error("width != height: "); + case 4: { // Квадратная матрица (2x2) с известными максимумами + input_data_ = {{10, 20}, {30, 40}}; + break; } } - - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ == output_data); + const auto &matrix = GetTestInputData(); + + // Отладочный вывод + std::cout << "Testing matrix: " << matrix.size() << "x" << (matrix.empty() ? 0 : matrix[0].size()) << std::endl; + + if (matrix.empty()) { + bool result = output_data.empty(); + std::cout << "Empty matrix test: " << (result ? "PASS" : "FAIL") << std::endl; + return result; + } + + if (output_data.size() != matrix[0].size()) { + std::cout << "Size mismatch: expected " << matrix[0].size() << ", got " << output_data.size() << std::endl; + return false; + } + + // Вычисляем ожидаемый результат + std::vector expected(matrix[0].size(), std::numeric_limits::min()); + for (size_t j = 0; j < matrix[0].size(); ++j) { + for (size_t i = 0; i < matrix.size(); ++i) { + if (matrix[i][j] > expected[j]) { + expected[j] = matrix[i][j]; + } + } + } + + // Сравниваем результаты + for (size_t i = 0; i < output_data.size(); ++i) { + if (output_data[i] != expected[i]) { + std::cout << "Column " << i << ": expected " << expected[i] << ", got " << output_data[i] << std::endl; + return false; + } + } + + std::cout << "Test PASSED" << std::endl; + return true; } InType GetTestInputData() final { @@ -60,16 +100,19 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; +// Тестовые случаи: (тип_теста, описание) +const std::array kTestParam = { + std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "large_matrix"), std::make_tuple(2, "single_column"), + std::make_tuple(3, "non_square_matrix"), std::make_tuple(4, "square_matrix")}; const auto kTestTasksList = std::tuple_cat( ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes), @@ -79,7 +122,7 @@ const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); const auto kPerfTestName = EgorovaLRunFuncTestsProcesses::PrintFuncTestName; -INSTANTIATE_TEST_SUITE_P(PicMatrixTests, EgorovaLRunFuncTestsProcesses, kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(MatrixTests, EgorovaLRunFuncTestsProcesses, kGtestValues, kPerfTestName); } // namespace diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp index de89119df..fc01f94c8 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -1,5 +1,7 @@ #include +#include + #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" #include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" #include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" @@ -8,15 +10,48 @@ namespace egorova_l_find_max_val_col_matrix { class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const int kCount_ = 100; + const int kMatrixSize_ = 10; // Очень маленькая матрица для теста InType input_data_{}; void SetUp() override { - input_data_ = kCount_; + // Создаем простую детерминированную матрицу + input_data_.resize(kMatrixSize_, std::vector(kMatrixSize_)); + + int counter = 1; + for (int i = 0; i < kMatrixSize_; ++i) { + for (int j = 0; j < kMatrixSize_; ++j) { + input_data_[i][j] = counter++; + } + } } bool CheckTestOutputData(OutType &output_data) final { - return input_data_ == output_data; + const auto &matrix = GetTestInputData(); + + if (matrix.empty() || output_data.empty()) { + return false; + } + + if (output_data.size() != matrix[0].size()) { + return false; + } + + // Вычисляем ожидаемый результат + std::vector expected(matrix[0].size(), std::numeric_limits::min()); + for (size_t j = 0; j < matrix[0].size(); ++j) { + for (size_t i = 0; i < matrix.size(); ++i) { + if (matrix[i][j] > expected[j]) { + expected[j] = matrix[i][j]; + } + } + } + + for (size_t i = 0; i < output_data.size(); ++i) { + if (output_data[i] != expected[i]) { + return false; + } + } + return true; } InType GetTestInputData() final { From 7fd14feb283ceb32adcee5c3e3b3f2315a4d20c4 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 09:35:49 +0000 Subject: [PATCH 04/27] 3 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 3 ++- tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index f5039f1ae..612385ef0 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -14,7 +14,8 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = std::vector(); + // Инициализируем выходной вектор явно, чтобы избежать предупреждений + GetOutput() = OutType(); } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index a9a27f751..fd73f057e 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -12,16 +12,15 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = std::vector(); + // Инициализируем выходной вектор явно + GetOutput() = OutType(); } bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { - // Разрешаем пустую матрицу if (GetInput().empty()) { return true; } - // Проверяем, что все строки имеют одинаковую длину size_t cols = GetInput()[0].size(); for (const auto &row : GetInput()) { if (row.size() != cols) { @@ -39,7 +38,6 @@ bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { const auto &matrix = GetInput(); - // Обрабатываем пустую матрицу if (matrix.empty()) { GetOutput() = std::vector(); return true; From 9e4a642d709b8bbf27261434a4fcd14834603d00 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 09:47:38 +0000 Subject: [PATCH 05/27] 4 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 612385ef0..315234120 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -14,8 +14,8 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - // Инициализируем выходной вектор явно, чтобы избежать предупреждений - GetOutput() = OutType(); + // Используем явную инициализацию для избежания предупреждений + GetOutput() = OutType{}; } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { From a5b71dac0a872dec93b0eda3a132231d9943534d Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:01:58 +0000 Subject: [PATCH 06/27] 5 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 6 ++++-- tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 315234120..744e2d062 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -11,11 +11,13 @@ namespace egorova_l_find_max_val_col_matrix { +#ifdef __GNUC__ +__attribute__((noinline)) +#endif EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - // Используем явную инициализацию для избежания предупреждений - GetOutput() = OutType{}; + GetOutput() = std::vector(); } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index fd73f057e..f01139708 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -9,11 +9,13 @@ namespace egorova_l_find_max_val_col_matrix { +#ifdef __GNUC__ +__attribute__((noinline)) +#endif EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - // Инициализируем выходной вектор явно - GetOutput() = OutType(); + GetOutput() = std::vector(); } bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { From dde499a2f3c4ef5cc571184a463201d6249cbc0b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:12:54 +0000 Subject: [PATCH 07/27] 6 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 744e2d062..80c01a641 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -11,12 +11,9 @@ namespace egorova_l_find_max_val_col_matrix { -#ifdef __GNUC__ -__attribute__((noinline)) -#endif EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; + GetInput() = std::move(in); // Используем перемещение вместо копирования GetOutput() = std::vector(); } From ef209bce8e8c22fa89254e3a3b20a69cadbb2e84 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:23:07 +0000 Subject: [PATCH 08/27] 7 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 80c01a641..5e0612f27 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -13,7 +13,7 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = std::move(in); // Используем перемещение вместо копирования + GetInput() = in; // копирование (безопасно) GetOutput() = std::vector(); } From ba5527ca22a7e868a5d4513847085fc9ef1a6119 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:31:14 +0000 Subject: [PATCH 09/27] 8 --- .../egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 5e0612f27..20b8c6b39 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -13,10 +13,12 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; // копирование (безопасно) - GetOutput() = std::vector(); -} + auto &input = GetInput(); + input.assign(in.begin(), in.end()); // <- безопасно для GCC14 + + GetOutput().clear(); +} bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { if (GetInput().empty()) { return true; From 454afaf324b2ef14845f5b3a4704777ce3984d3b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:42:14 +0000 Subject: [PATCH 10/27] 9 --- .../egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 20b8c6b39..823619b2f 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -13,11 +13,8 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - - auto &input = GetInput(); - input.assign(in.begin(), in.end()); // <- безопасно для GCC14 - - GetOutput().clear(); + GetInput() = in; + GetOutput() = std::vector(0); } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { if (GetInput().empty()) { From 131082f2fdac73b9bd3836527e1b4e89fecc98af Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 10:51:11 +0000 Subject: [PATCH 11/27] 10 --- tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 823619b2f..9507aaad5 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -13,7 +13,8 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; + InType temp = in; // Создаем временную копию + GetInput() = std::move(temp); // Перемещаем GetOutput() = std::vector(0); } bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { From 1bfec778323904c845266e114c4f7bc1d22c4a3f Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 11:04:27 +0000 Subject: [PATCH 12/27] 11 --- .../mpi/src/ops_mpi.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 9507aaad5..3c2d3f12a 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -11,12 +11,22 @@ namespace egorova_l_find_max_val_col_matrix { +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnull-dereference" +#endif + EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); InType temp = in; // Создаем временную копию GetInput() = std::move(temp); // Перемещаем GetOutput() = std::vector(0); } + +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { if (GetInput().empty()) { return true; From cc9e0020a38749e2e00b89b6743d5e3f8119f29b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 11:11:55 +0000 Subject: [PATCH 13/27] 12 --- .../seq/src/ops_seq.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index f01139708..e9721496b 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -10,14 +10,21 @@ namespace egorova_l_find_max_val_col_matrix { #ifdef __GNUC__ -__attribute__((noinline)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnull-dereference" #endif -EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { + +EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = std::vector(); + InType temp = in; // Создаем временную копию + GetInput() = std::move(temp); // Перемещаем + GetOutput() = std::vector(0); } +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { if (GetInput().empty()) { return true; From 4eb4946f671e29b8bf8c9e5b6404ee86771f40ea Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 11:19:32 +0000 Subject: [PATCH 14/27] 13 --- tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index e9721496b..4a8959615 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -14,7 +14,7 @@ namespace egorova_l_find_max_val_col_matrix { # pragma GCC diagnostic ignored "-Wnull-dereference" #endif -EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { +EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); InType temp = in; // Создаем временную копию GetInput() = std::move(temp); // Перемещаем From a993cabab257bb544296fa155d01316e9672b86b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 23:25:57 +0000 Subject: [PATCH 15/27] 14 --- .../seq/src/ops_seq.cpp | 12 +- .../tests/functional/main.cpp | 111 ++++++++++++------ .../tests/performance/main.cpp | 4 +- 3 files changed, 80 insertions(+), 47 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index 4a8959615..09e3f1705 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -9,22 +9,12 @@ namespace egorova_l_find_max_val_col_matrix { -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wnull-dereference" -#endif - EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - InType temp = in; // Создаем временную копию - GetInput() = std::move(temp); // Перемещаем + GetInput() = in; GetOutput() = std::vector(0); } -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { if (GetInput().empty()) { return true; diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 20fa98908..f0e97ca28 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -28,48 +28,81 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); int test_type = std::get<0>(test_params); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dist(10, 50); // Уменьшим диапазон - switch (test_type) { - case 0: { // Пустая матрица + case 0: // Пустая матрица input_data_ = {}; break; - } - case 1: { // Большая матрица (4x4) - input_data_ = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; + + case 1: // Нулевая матрица (1x0) + input_data_ = {{}}; break; - } - case 2: { // 1 столбец - input_data_ = {{1}, {5}, {3}, {7}}; + + case 2: // Один столбец + input_data_ = {{5}, {-3}, {10}, {1}}; break; - } - case 3: { // Неквадратная матрица (3x2) - input_data_ = {{1, 2}, {3, 4}, {5, 6}}; + + case 3: // Одна строка + input_data_ = {{8, -2, 15, 0, -7}}; break; - } - case 4: { // Квадратная матрица (2x2) с известными максимумами - input_data_ = {{10, 20}, {30, 40}}; + + case 4: // Квадратная матрица 3x3 + input_data_ = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + break; + + case 5: // Неквадратная матрица (2x4) + input_data_ = {{10, 20, 30, 40}, {50, 60, 70, 80}}; + break; + + case 6: // Матрица с отрицательными значениями + input_data_ = {{-5, -2, -10}, {-1, -8, -3}, {-7, -4, -6}}; + break; + + case 7: // Матрица с одинаковыми значениями + input_data_ = {{5, 5, 5}, {5, 5, 5}, {5, 5, 5}}; + break; + + case 8: // Матрица с максимальным элементом в разных столбцах + input_data_ = {{1, 100, 2}, {50, 3, 200}, {10, 4, 5}}; + break; + + case 9: // Большая матрица 5x5 + input_data_ = { + {15, 8, 22, 4, 19}, {7, 25, 11, 3, 14}, {9, 2, 30, 17, 6}, {12, 5, 1, 28, 10}, {20, 13, 16, 21, 0}}; + break; + + case 10: // Матрица с одним элементом + input_data_ = {{42}}; + break; + + case 11: // Матрица где максимум в первом столбце + input_data_ = {{99, 1, 2}, {88, 3, 4}, {77, 5, 6}}; + break; + + case 12: // Матрица где максимум в последнем столбце + input_data_ = {{1, 2, 100}, {3, 4, 90}, {5, 6, 80}}; + break; + + case 13: // Матрица с нулевыми значениями + input_data_ = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; break; - } } } bool CheckTestOutputData(OutType &output_data) final { const auto &matrix = GetTestInputData(); - // Отладочный вывод - std::cout << "Testing matrix: " << matrix.size() << "x" << (matrix.empty() ? 0 : matrix[0].size()) << std::endl; - + // Проверка пустой матрицы if (matrix.empty()) { - bool result = output_data.empty(); - std::cout << "Empty matrix test: " << (result ? "PASS" : "FAIL") << std::endl; - return result; + return output_data.empty(); + } + + // Проверка нулевой матрицы (столбцы нулевой длины) + if (matrix[0].empty()) { + return output_data.empty(); } + // Проверка размера выходного вектора if (output_data.size() != matrix[0].size()) { - std::cout << "Size mismatch: expected " << matrix[0].size() << ", got " << output_data.size() << std::endl; return false; } @@ -86,12 +119,10 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = { - std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "large_matrix"), std::make_tuple(2, "single_column"), - std::make_tuple(3, "non_square_matrix"), std::make_tuple(4, "square_matrix")}; - -const auto kTestTasksList = std::tuple_cat( - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_example_processes)); +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), + std::make_tuple(1, "zero_matrix"), + std::make_tuple(2, "single_column"), + std::make_tuple(3, "single_row"), + std::make_tuple(4, "square_3x3"), + std::make_tuple(5, "non_square_2x4"), + std::make_tuple(6, "negative_values"), + std::make_tuple(7, "same_values"), + std::make_tuple(8, "max_in_different_cols"), + std::make_tuple(9, "large_5x5"), + std::make_tuple(10, "single_element"), + std::make_tuple(11, "max_in_first_col"), + std::make_tuple(12, "max_in_last_col"), + std::make_tuple(13, "zero_values")}; + +const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp index fc01f94c8..d60fe02cd 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -10,7 +10,7 @@ namespace egorova_l_find_max_val_col_matrix { class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const int kMatrixSize_ = 10; // Очень маленькая матрица для теста + const int kMatrixSize_ = 5000; // большая матрица InType input_data_{}; void SetUp() override { @@ -65,7 +65,7 @@ TEST_P(EgorovaLRunPerfTestProcesses, EgorovaLRunPerfModes) { const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_example_processes); + PPC_SETTINGS_egorova_l_find_max_val_col_matrix); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); From fc65adf67e4d3dbfe621eda145a2c9491808eb97 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Tue, 18 Nov 2025 23:33:59 +0000 Subject: [PATCH 16/27] 15 --- .../seq/src/ops_seq.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index 09e3f1705..27d84fe5c 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -9,12 +9,21 @@ namespace egorova_l_find_max_val_col_matrix { +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnull-dereference" +#endif + EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; GetOutput() = std::vector(0); } +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { if (GetInput().empty()) { return true; From 6cb75081f98aab8732fefb94608bff8526b34314 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Wed, 19 Nov 2025 17:22:51 +0000 Subject: [PATCH 17/27] 16 --- .../common/include/common.hpp | 4 +- .../mpi/src/ops_mpi.cpp | 137 +++++++++++------- .../seq/src/ops_seq.cpp | 37 ++--- .../tests/functional/main.cpp | 18 +-- .../tests/performance/main.cpp | 27 ++-- 5 files changed, 127 insertions(+), 96 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp index 667139118..09cabbfc8 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/common/include/common.hpp @@ -7,7 +7,9 @@ #include "task/include/task.hpp" namespace egorova_l_find_max_val_col_matrix { - +// задала подходящие под мою задачу типы данных +// на вход принимаю матрицу заданную парой векторов +// на выход передается вектор максимальных значений столбцов матрицы using InType = std::vector>; using OutType = std::vector; using TestType = std::tuple; diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 3c2d3f12a..be31d35ea 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -1,13 +1,11 @@ -#include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" - #include #include +#include #include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" -#include "util/include/util.hpp" namespace egorova_l_find_max_val_col_matrix { @@ -18,8 +16,7 @@ namespace egorova_l_find_max_val_col_matrix { EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); - InType temp = in; // Создаем временную копию - GetInput() = std::move(temp); // Перемещаем + GetInput() = in; GetOutput() = std::vector(0); } @@ -28,44 +25,49 @@ EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) #endif bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { - if (GetInput().empty()) { + const auto &matrix = GetInput(); + + if (matrix.empty()) { return true; } - size_t cols = GetInput()[0].size(); - for (const auto &row : GetInput()) { - if (row.size() != cols) { - return false; - } + if (matrix[0].empty()) { + return true; } - return GetOutput().empty(); + const std::size_t cols = matrix[0].size(); + return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); } bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { return true; } +// Разделим сложную функцию на части для уменьшения cognitive complexity bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - // Определяем, пустая ли матрица - int is_empty = 0; - if (rank == 0) { - is_empty = GetInput().empty() ? 1 : 0; + if (!ValidationImpl()) { + GetOutput() = std::vector(); + return true; } - MPI_Bcast(&is_empty, 1, MPI_INT, 0, MPI_COMM_WORLD); - if (is_empty) { + const auto &matrix = GetInput(); + + if (matrix.empty() || matrix[0].empty()) { GetOutput() = std::vector(); - MPI_Barrier(MPI_COMM_WORLD); return true; } - // Бродкастим размеры матрицы - int rows = 0, cols = 0; + return RunMPIAlgorithm(); +} + +bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int rows = 0; + int cols = 0; if (rank == 0) { rows = static_cast(GetInput().size()); cols = static_cast(GetInput()[0].size()); @@ -74,64 +76,89 @@ bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); - // Создаем и бродкастим плоскую матрицу - std::vector flat_matrix(rows * cols); + if (rows == 0 || cols == 0) { + GetOutput() = std::vector(); + return true; + } + + std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); + auto [start_col, local_cols_count] = CalculateColumnDistribution(rank, size, cols); + std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); + std::vector all_max = GatherResults(local_max, rank, size, cols); + + GetOutput() = all_max; + MPI_Barrier(MPI_COMM_WORLD); + return true; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int rank, int rows, int cols) { + std::vector flat_matrix(static_cast(rows) * static_cast(cols)); + if (rank == 0) { - for (int i = 0; i < rows; ++i) { - for (int j = 0; j < cols; ++j) { - flat_matrix[i * cols + j] = GetInput()[i][j]; + const auto &matrix = GetInput(); + for (int ii = 0; ii < rows; ++ii) { + for (int jj = 0; jj < cols; ++jj) { + flat_matrix[static_cast(ii) * static_cast(cols) + static_cast(jj)] = + matrix[ii][jj]; } } } + MPI_Bcast(flat_matrix.data(), rows * cols, MPI_INT, 0, MPI_COMM_WORLD); + return flat_matrix; +} + +std::pair EgorovaLFindMaxValColMatrixMPI::CalculateColumnDistribution(int rank, int size, int cols) { + const int cols_per_proc = cols / size; + const int remainder = cols % size; - // Распределяем столбцы между процессами - int cols_per_proc = cols / size; - int remainder = cols % size; + int start_col = 0; + int local_cols_count = 0; - // Определяем диапазон столбцов для текущего процесса - int start_col, local_cols_count; if (rank < remainder) { start_col = rank * (cols_per_proc + 1); local_cols_count = cols_per_proc + 1; } else { - start_col = remainder * (cols_per_proc + 1) + (rank - remainder) * cols_per_proc; + start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); local_cols_count = cols_per_proc; } - // Каждый процесс вычисляет максимумы ТОЛЬКО для своих столбцов + return {start_col, local_cols_count}; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, + int cols, int start_col, int local_cols_count) { std::vector local_max(local_cols_count, std::numeric_limits::min()); for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { - int global_col = start_col + local_idx; + const int global_col = start_col + local_idx; for (int row = 0; row < rows; ++row) { - int value = flat_matrix[row * cols + global_col]; - if (value > local_max[local_idx]) { - local_max[local_idx] = value; - } + const int value = flat_matrix[(row * cols) + global_col]; + local_max[local_idx] = std::max(value, local_max[local_idx]); } } - // Подготавливаем массивы для сбора результатов + return local_max; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector &local_max, int rank, int size, + int cols) { + const int cols_per_proc = cols / size; + const int remainder = cols % size; + std::vector all_max(cols, std::numeric_limits::min()); std::vector recv_counts(size); std::vector displs(size); - // Определяем сколько столбцов у каждого процесса - for (int i = 0; i < size; ++i) { - recv_counts[i] = (i < remainder) ? (cols_per_proc + 1) : cols_per_proc; - displs[i] = (i == 0) ? 0 : displs[i - 1] + recv_counts[i - 1]; + for (int ii = 0; ii < size; ++ii) { + recv_counts[ii] = (ii < remainder) ? (cols_per_proc + 1) : cols_per_proc; + displs[ii] = (ii == 0) ? 0 : displs[ii - 1] + recv_counts[ii - 1]; } - // Собираем результаты от всех процессов - MPI_Allgatherv(local_max.data(), local_cols_count, MPI_INT, all_max.data(), recv_counts.data(), displs.data(), - MPI_INT, MPI_COMM_WORLD); - - // Все процессы получают полный результат - GetOutput() = all_max; + MPI_Allgatherv(local_max.data(), static_cast(local_max.size()), MPI_INT, all_max.data(), recv_counts.data(), + displs.data(), MPI_INT, MPI_COMM_WORLD); - MPI_Barrier(MPI_COMM_WORLD); - return true; + return all_max; } bool EgorovaLFindMaxValColMatrixMPI::PostProcessingImpl() { diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index 27d84fe5c..c9381984b 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -1,11 +1,9 @@ -#include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" - #include +#include #include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" -#include "util/include/util.hpp" namespace egorova_l_find_max_val_col_matrix { @@ -25,18 +23,18 @@ EgorovaLFindMaxValColMatrixSEQ::EgorovaLFindMaxValColMatrixSEQ(const InType &in) #endif bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { - if (GetInput().empty()) { + const auto &matrix = GetInput(); + + if (matrix.empty()) { return true; } - size_t cols = GetInput()[0].size(); - for (const auto &row : GetInput()) { - if (row.size() != cols) { - return false; - } + if (matrix[0].empty()) { + return true; } - return GetOutput().empty(); + const std::size_t cols = matrix[0].size(); + return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); } bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { @@ -46,20 +44,23 @@ bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { const auto &matrix = GetInput(); - if (matrix.empty()) { + if (!ValidationImpl()) { + GetOutput() = std::vector(); + return true; + } + + if (matrix.empty() || matrix[0].empty()) { GetOutput() = std::vector(); return true; } - size_t rows = matrix.size(); - size_t cols = matrix[0].size(); + const std::size_t rows = matrix.size(); + const std::size_t cols = matrix[0].size(); std::vector result(cols, std::numeric_limits::min()); - for (size_t j = 0; j < cols; ++j) { - for (size_t i = 0; i < rows; ++i) { - if (matrix[i][j] > result[j]) { - result[j] = matrix[i][j]; - } + for (std::size_t jj = 0; jj < cols; ++jj) { + for (std::size_t ii = 0; ii < rows; ++ii) { + result[jj] = std::max(matrix[ii][jj], result[jj]); } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index f0e97ca28..74850cad5 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -3,8 +3,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -85,6 +84,9 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests expected(matrix[0].size(), std::numeric_limits::min()); - for (size_t j = 0; j < matrix[0].size(); ++j) { - for (size_t i = 0; i < matrix.size(); ++i) { - if (matrix[i][j] > expected[j]) { - expected[j] = matrix[i][j]; - } + for (std::size_t jj = 0; jj < matrix[0].size(); ++jj) { + for (std::size_t ii = 0; ii < matrix.size(); ++ii) { + expected[jj] = std::max(matrix[ii][jj], expected[jj]); } } // Сравниваем результаты - for (size_t i = 0; i < output_data.size(); ++i) { - if (output_data[i] != expected[i]) { + for (std::size_t ii = 0; ii < output_data.size(); ++ii) { + if (output_data[ii] != expected[ii]) { return false; } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp index d60fe02cd..1f664f57f 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -1,6 +1,9 @@ #include -#include +#include +#include +#include +#include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" #include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" @@ -10,17 +13,17 @@ namespace egorova_l_find_max_val_col_matrix { class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const int kMatrixSize_ = 5000; // большая матрица - InType input_data_{}; + const std::size_t kMatrixSize_ = 5000; // большая матрица + InType input_data_; void SetUp() override { // Создаем простую детерминированную матрицу input_data_.resize(kMatrixSize_, std::vector(kMatrixSize_)); int counter = 1; - for (int i = 0; i < kMatrixSize_; ++i) { - for (int j = 0; j < kMatrixSize_; ++j) { - input_data_[i][j] = counter++; + for (std::size_t ii = 0; ii < kMatrixSize_; ++ii) { + for (std::size_t jj = 0; jj < kMatrixSize_; ++jj) { + input_data_[ii][jj] = counter++; } } } @@ -38,16 +41,14 @@ class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests expected(matrix[0].size(), std::numeric_limits::min()); - for (size_t j = 0; j < matrix[0].size(); ++j) { - for (size_t i = 0; i < matrix.size(); ++i) { - if (matrix[i][j] > expected[j]) { - expected[j] = matrix[i][j]; - } + for (size_t jj = 0; jj < matrix[0].size(); ++jj) { + for (size_t ii = 0; ii < matrix.size(); ++ii) { + expected[jj] = std::max(matrix[ii][jj], expected[jj]); } } - for (size_t i = 0; i < output_data.size(); ++i) { - if (output_data[i] != expected[i]) { + for (size_t ii = 0; ii < output_data.size(); ++ii) { + if (output_data[ii] != expected[ii]) { return false; } } From dbe24a698892219684850388de0bc307e91a13ed Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Wed, 19 Nov 2025 17:45:36 +0000 Subject: [PATCH 18/27] 17 --- .../mpi/include/ops_mpi.hpp | 11 ++++++++++ .../mpi/src/ops_mpi.cpp | 20 +++++++++++++------ .../seq/include/ops_seq.hpp | 2 ++ .../seq/src/ops_seq.cpp | 14 +++++++++++-- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp index a568fb1b8..325da7d45 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" #include "task/include/task.hpp" @@ -17,6 +20,14 @@ class EgorovaLFindMaxValColMatrixMPI : public BaseTask { bool PreProcessingImpl() override; bool RunImpl() override; bool PostProcessingImpl() override; + + // Объявления вспомогательных методов + bool RunMPIAlgorithm(); + std::vector CreateAndBroadcastMatrix(int rank, int rows, int cols); + std::pair CalculateColumnDistribution(int rank, int size, int cols); + std::vector CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, + int local_cols_count); + std::vector GatherResults(const std::vector &local_max, int size, int cols); }; } // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index be31d35ea..29f176a7a 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -1,3 +1,5 @@ +#include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp" + #include #include @@ -36,14 +38,19 @@ bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { } const std::size_t cols = matrix[0].size(); - return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); + for (const auto &row : matrix) { + if (row.size() != cols) { + return false; + } + } + + return true; } bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { return true; } -// Разделим сложную функцию на части для уменьшения cognitive complexity bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { if (!ValidationImpl()) { GetOutput() = std::vector(); @@ -84,7 +91,7 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); auto [start_col, local_cols_count] = CalculateColumnDistribution(rank, size, cols); std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); - std::vector all_max = GatherResults(local_max, rank, size, cols); + std::vector all_max = GatherResults(local_max, size, cols); GetOutput() = all_max; MPI_Barrier(MPI_COMM_WORLD); @@ -134,15 +141,16 @@ std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std: const int global_col = start_col + local_idx; for (int row = 0; row < rows; ++row) { const int value = flat_matrix[(row * cols) + global_col]; - local_max[local_idx] = std::max(value, local_max[local_idx]); + if (value > local_max[local_idx]) { + local_max[local_idx] = value; + } } } return local_max; } -std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector &local_max, int rank, int size, - int cols) { +std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector &local_max, int size, int cols) { const int cols_per_proc = cols / size; const int remainder = cols % size; diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp index bec18f5ec..d2f5b5653 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" #include "task/include/task.hpp" diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index c9381984b..a36d1916b 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -1,3 +1,5 @@ +#include "egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp" + #include #include #include @@ -34,7 +36,13 @@ bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { } const std::size_t cols = matrix[0].size(); - return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); + for (const auto &row : matrix) { + if (row.size() != cols) { + return false; + } + } + + return true; } bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { @@ -60,7 +68,9 @@ bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { for (std::size_t jj = 0; jj < cols; ++jj) { for (std::size_t ii = 0; ii < rows; ++ii) { - result[jj] = std::max(matrix[ii][jj], result[jj]); + if (matrix[ii][jj] > result[jj]) { + result[jj] = matrix[ii][jj]; + } } } From 058955eee762848046f01081219284411388995e Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Thu, 20 Nov 2025 00:39:46 +0000 Subject: [PATCH 19/27] 18 --- .../mpi/include/ops_mpi.hpp | 8 ++++---- .../mpi/src/ops_mpi.cpp | 15 ++++----------- .../seq/include/ops_seq.hpp | 2 -- .../seq/src/ops_seq.cpp | 13 +++---------- .../tests/functional/main.cpp | 14 ++++++++++++-- 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp index 325da7d45..f671cd0f3 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp @@ -24,10 +24,10 @@ class EgorovaLFindMaxValColMatrixMPI : public BaseTask { // Объявления вспомогательных методов bool RunMPIAlgorithm(); std::vector CreateAndBroadcastMatrix(int rank, int rows, int cols); - std::pair CalculateColumnDistribution(int rank, int size, int cols); - std::vector CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, - int local_cols_count); - std::vector GatherResults(const std::vector &local_max, int size, int cols); + static std::pair CalculateColumnDistribution(int rank, int size, int cols); + static std::vector CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, + int local_cols_count); + static std::vector GatherResults(const std::vector &local_max, int size, int cols); }; } // namespace egorova_l_find_max_val_col_matrix diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index 29f176a7a..a171be81f 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" @@ -38,13 +39,7 @@ bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() { } const std::size_t cols = matrix[0].size(); - for (const auto &row : matrix) { - if (row.size() != cols) { - return false; - } - } - - return true; + return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); } bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { @@ -105,7 +100,7 @@ std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int ra const auto &matrix = GetInput(); for (int ii = 0; ii < rows; ++ii) { for (int jj = 0; jj < cols; ++jj) { - flat_matrix[static_cast(ii) * static_cast(cols) + static_cast(jj)] = + flat_matrix[(static_cast(ii) * static_cast(cols)) + static_cast(jj)] = matrix[ii][jj]; } } @@ -141,9 +136,7 @@ std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std: const int global_col = start_col + local_idx; for (int row = 0; row < rows; ++row) { const int value = flat_matrix[(row * cols) + global_col]; - if (value > local_max[local_idx]) { - local_max[local_idx] = value; - } + local_max[local_idx] = std::max(value, local_max[local_idx]); } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp index d2f5b5653..bec18f5ec 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/include/ops_seq.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" #include "task/include/task.hpp" diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index a36d1916b..fb0bd344f 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -36,13 +36,8 @@ bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { } const std::size_t cols = matrix[0].size(); - for (const auto &row : matrix) { - if (row.size() != cols) { - return false; - } - } - - return true; + // ЗАМЕНИ цикл на std::ranges::all_of + return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); } bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { @@ -68,9 +63,7 @@ bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { for (std::size_t jj = 0; jj < cols; ++jj) { for (std::size_t ii = 0; ii < rows; ++ii) { - if (matrix[ii][jj] > result[jj]) { - result[jj] = matrix[ii][jj]; - } + result[jj] = std::max(matrix[ii][jj], result[jj]); } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 74850cad5..86bd8d132 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -85,6 +85,14 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = {std::make_tuple(0, "empty_matrix"), +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), std::make_tuple(3, "single_row"), @@ -154,7 +162,9 @@ const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(10, "single_element"), std::make_tuple(11, "max_in_first_col"), std::make_tuple(12, "max_in_last_col"), - std::make_tuple(13, "zero_values")}; + std::make_tuple(13, "zero_values"), + std::make_tuple(14, "many_processes_few_columns"), + std::make_tuple(15, "validation_failure_case")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix), From a5a8a22129b32b73c14f396ad4a980807413520b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Thu, 20 Nov 2025 14:57:23 +0000 Subject: [PATCH 20/27] this otchet --- .../report.md | 326 ++++++++++++++++++ .../seq/src/ops_seq.cpp | 1 - .../tests/functional/main.cpp | 19 +- 3 files changed, 338 insertions(+), 8 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/report.md b/tasks/egorova_l_find_max_val_col_matrix/report.md index e69de29bb..6f46008eb 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/report.md +++ b/tasks/egorova_l_find_max_val_col_matrix/report.md @@ -0,0 +1,326 @@ +# Нахождение наиболее отличающихся по значению соседних элементов вектора + +- Студент: Егорова Лариса Алексеевна, группа 3823Б1ФИ1 +- Технология: SEQ | MPI +- Вариант: 16 + +## 1. Введение +Данная лабораторная работа посвящена решению задачи поиска максимальных элементов в столбцах матрицы. Для достижения поставленной цели были разработаны и реализованы два подхода: последовательный алгоритм и параллельная реализация с использованием библиотеки MPI. Основной задачей исследования является сравнительный анализ эффективности данных реализаций и оценка преимуществ параллелизации вычислительного процесса. + +## 2. Постановка задачи +Для заданной матрицы размером M×N необходимо найти вектор максимальных значений для каждого столбца. +Формально: для каждого столбца j найти max(a[i][j]) для всех i от 0 до M-1. + +Входные данные: матрица целых чисел +Выходные данные: вектор максимальных значений для каждого столбца + +Особые случаи: + +- Пустая матрица → пустой вектор +- Матрица с нулевыми столбцами → пустой вектор +- Некорректная матрица (разные длины строк) → ошибка валидации + +## 3. Базовый алгоритм (Последовательный) +Последовательный алгоритм проходит по каждому столбцу матрицы и находит максимальное значение: + +for (j от 0 до N-1): + max_val = MIN_INT + for (i от 0 до M-1): + if matrix[i][j] > max_val: + max_val = matrix[i][j] + result[j] = max_val + +Результатом выполнения алгоритма будет вектор максимальных значений result. + +Сложность алгоритма: O(M×N) + + +## 4. Схема распараллеливания + +### 4.1 Общая архитектура +Алгоритм использует декомпозицию по столбцам — каждый процесс получает свой набор столбцов для независимой обработки. Такой подход обеспечивает максимальное распараллеливание при минимальных коммуникационных затратах. + +### 4.2 Распределение данных +Столбцы распределяются по процессам с адаптивным балансированием нагрузки. Если количество столбцов N не делится нацело на число процессов P, первые R процессов (R = N mod P) получают на один столбец больше. Это гарантирует, что разница в нагрузке между процессами не превышает одного столбца. + +Исходная матрица преобразуется в плоский массив с построчным хранением для эффективной передачи через MPI. + +### 4.3 Коммуникационная схема +Процесс выполняется в три этапа: +- Распространение данных — процесс 0 рассылает размеры матрицы и данные всем процессам через MPI_Bcast +- Параллельные вычисления — каждый процесс находит максимумы в своих столбцах независимо +- Сбор результатов — все процессы обмениваются результатами через MPI_Allgatherv + +### 4.4 Преимущества и ограничения +Преимущества: +- минимальные коммуникации (только 2 передачи) +- Идеальная балансировка нагрузки +- Простота реализации +- Масштабируемость + +Ограничения: +- Каждый процесс хранит полную копию матрицы +- Ограничение по памяти на одном узле + + +## 5. Детали реализации +Структура кода: +- ..\MPI\ppc-2025-processes-informatics\tasks\egorova_l_find_max_val_col_matrix\seq\src\ops_seq.cpp — последовательная реализация +- ..\MPI\ppc-2025-processes-informatics\tasks\egorova_l_find_max_val_col_matrix\mpi\src\ops_mpi.cpp — MPI реализация + +Тесты: +- ..\MPI\ppc-2025-processes-informatics\tasks\egorova_l_find_max_val_col_matrix\tests\functional\main.cpp — функциональные +- ..\MPI\ppc-2025-processes-informatics\tasks\egorova_l_find_max_val_col_matrix\tests\performance\main.cpp — на производительность + +## 6. Экспериментальная установка + +### 6.1 Оборудование и ПО +- CPU: AMD Ryzen 5 2600 Six-Core Processor 3.40 GHz (6 ядер, 12 потоков) +- RAM: 16GB DDR4 +- ОС: Windows 10 Pro +- Тип сборки: Release + +### 6.2 Функциональное тестирование +Для проверки корректности реализации проведено комплексное функциональное тестирование, охватывающее различные сценарии работы алгоритма: + +Базовые случаи: +- Пустая матрица — проверка обработки граничного условия +- Матрица с нулевыми столбцами — валидация обработки вырожденных случаев +- Матрица 1×1 — тестирование минимального размера + +Структурные тесты: +- Один столбец — проверка обработки векторного случая +- Одна строка — тестирование горизонтальной матрицы +- Квадратные матрицы 3×3 и 5×5 — стандартные сценарии + +Семантические тесты: +- Отрицательные значения — проверка корректности сравнения +- Одинаковые значения — тестирование стабильности при равенстве элементов +- Нулевые значения — валидация работы с нулями + +Сценарии расположения максимумов: +- Максимум в первом столбце — проверка граничных условий +- Максимум в последнем столбце — тестирование конечных элементов +- Максимумы в разных столбцах — комплексная проверка распределения + +Неквадратные матрицы: +- Прямоугольные матрицы 2×4 и 3×2 — тестирование асимметричных случаев +- Большая матрица 10×1 — проверка обработки длинных столбцов +- Матрица 1×10 — тестирование длинных строк + +### 6.3 Тестирование производительности +Методология тестирования: + +- Размер тестовой матрицы: 5000×5000 элементов (25 миллионов значений) и 10000х10000 (100 миллионов значений) +- Тип данных: 32-битные целые числа (int) +- Количество процессов: 1, 2, 4, 8 +- Количество запусков: 5 для каждого конфигурации + +Генерация тестовых данных: +- Используется детерминистический алгоритм заполнения +- Последовательное увеличение значений для предсказуемости результатов +- Гарантированное наличие уникальных максимальных значений в каждом столбце + +Метрики производительности: +- Время выполнения (секунды) +- Ускорение (speedup) относительно последовательной версии +- Эффективность параллелизации (efficiency) +- Потребление памяти + +## 7. Результаты и обсуждение + +### 7.1 Корректность +Реализованные последовательная и MPI-версии алгоритма успешно прошли все функциональные тесты. Проверка корректности осуществлялась через сравнение результатов обеих реализаций с эталонными значениями, вычисленными аналитически. Особое внимание уделялось обработке граничных случаев: пустых матриц, матриц с нулевыми столбцами, матриц минимального размера 1×1. Все тесты подтвердили идентичность результатов параллельной и последовательной версий. + +### 7.2 Проведение тестов +Для оценки производительности алгоритма поиска максимальных значений по столбцам матрицы были проведены тесты на двух размерах матриц: 5000×5000 (25 миллионов значений) и 10000×10000 (100 миллионов значений). Результаты представлены в таблицах: + +1. Матрица 5000×5000 +|Режим |Процессы |Время, с |Ускорение |Эффективность| +|-------|---------|---------|-----------|-------------| +|seq |1 |0.22558 |1.00 |N/A | +|mpi |2 |0.20185 |1.12 |56.0% | +|mpi |4 |0.23712 |0.95 |23.8% | +|mpi |8 |0.29534 |0.76 |9.5% | + +2. Матрица 10000x10000 +|Режим |Процессы |Время, с |Ускорение |Эффективность| +|-------|---------|---------|-----------|-------------| +|seq |1 |0.26388 |1.00 |N/A | +|mpi |2 |0.21299 |1.24 |61.95% | +|mpi |4 |0.25952 |1.02 |25.4% | +|mpi |8 |0.30015 |0.88 |10.99% | + +Ускорение вычислялось по формуле (seq_time / mpi_time) +Эффективность вычислялась по формуле (Ускорение / N) * 100%, где N - количество процессов + +### 7.3 Анализ результатов + +#### 7.3.1 Влияние размера задачи на производительность +Наблюдается значительное улучшение эффективности параллелизации с ростом размера матрицы: + +Для матрицы 5000×5000: +- Лучшая эффективность: 55.87% на 2 процессах +- MPI с 1 процессом медленнее sequential версии + +Для матрицы 10000×10000: +- Лучшая эффективность: 61.95% на 2 процессах (+6.08%) +- MPI с 1 процессом быстрее sequential версии +- Ускорение улучшилось с 1.12× до 1.24× + +#### 7.3.2 Оптимальные конфигурации +Для обеих размерностей наилучшая производительность достигается при использовании 2 процессов MPI: +Матрица 5000×5000: время 0.20186 с, ускорение 1.12× +Матрица 10000×10000: время 0.21299 с, ускорение 1.24× + +#### 7.3.3 Динамика масштабируемости +Обе размерности демонстрируют схожую динамику: + +- Пик эффективности на 2 процессах; +- Резкое снижение эффективности при 4 и более процессах; +- Наилучшее соотношение вычислений и коммуникаций при 2 процессах. + +#### 7.3.4 Выводы по производительности: +Алгоритм демонстрирует хорошую масштабируемость для средних и больших размеров задач, что подтверждается ростом эффективности с 55.87% до 61.95% при увеличении размера матрицы. + +Оптимальная конфигурация - 2 процесса MPI, что обеспечивает баланс между вычислительной нагрузкой и коммуникационными затратами. + +Ограниченная масштабируемость при большом количестве процессов обусловлена преобладанием коммуникационных операций (MPI_Allgatherv) над вычислительными при распределении на 4 и более процессов. + +Практическая применимость: разработанная реализация эффективна для обработки матриц средних и больших размеров, где вычислительная сложность преобладает над накладными расходами параллелизации. + +## 8. Заключение +Был разработан алгоритм для поиска максимальных значений в столбцах матрицы. Реализованные последовательная и параллельная MPI-реализации успешно проходят все функциональные тесты, включая обработку граничных случаев (пустые матрицы, матрицы с нулевыми столбцами) и работу с различными типами данных. + +Проведенное исследование производительности на матрицах размером 5000×5000 и 10000×10000 показало, что MPI-реализация демонстрирует положительное ускорение по сравнению с последовательной версией. Наилучшие результаты достигаются при использовании 2 процессов: + +Для матрицы 5000×5000: ускорение 1.12×, эффективность 55.87% + +Для матрицы 10000×10000: ускорение 1.24×, эффективность 61.95% + +## 9. Источники +- Лекции Сысоева Александра Владимировича +- Практические занятия Нестерова Александра Юрьевича и Оболенского Арсения Андреевича +- Open MPI Documentation. https://www.open-mpi.org/doc/ +- Introduction to Parallel Computing. https://computing.llnl.gov/tutorials/parallel_comp/ +- MPI Tutorial for Beginners. https://mpitutorial.com/ +- C++ Standard Library Reference. https://en.cppreference.com/ +- "Основы MPI программирования". https://habr.com/ru/articles/121925/ + +## Приложение +```cpp +bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { + if (!ValidationImpl()) { + GetOutput() = std::vector(); + return true; + } + + const auto &matrix = GetInput(); + + if (matrix.empty() || matrix[0].empty()) { + GetOutput() = std::vector(); + return true; + } + + return RunMPIAlgorithm(); +} + +bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int rows = 0; + int cols = 0; + if (rank == 0) { + rows = static_cast(GetInput().size()); + cols = static_cast(GetInput()[0].size()); + } + + MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); + + if (rows == 0 || cols == 0) { + GetOutput() = std::vector(); + return true; + } + + std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); + auto [start_col, local_cols_count] = CalculateColumnDistribution(rank, size, cols); + std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); + std::vector all_max = GatherResults(local_max, size, cols); + + GetOutput() = all_max; + MPI_Barrier(MPI_COMM_WORLD); + return true; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int rank, int rows, int cols) { + std::vector flat_matrix(static_cast(rows) * static_cast(cols)); + + if (rank == 0) { + const auto &matrix = GetInput(); + for (int ii = 0; ii < rows; ++ii) { + for (int jj = 0; jj < cols; ++jj) { + flat_matrix[(static_cast(ii) * static_cast(cols)) + static_cast(jj)] = + matrix[ii][jj]; + } + } + } + + MPI_Bcast(flat_matrix.data(), rows * cols, MPI_INT, 0, MPI_COMM_WORLD); + return flat_matrix; +} + +std::pair EgorovaLFindMaxValColMatrixMPI::CalculateColumnDistribution(int rank, int size, int cols) { + const int cols_per_proc = cols / size; + const int remainder = cols % size; + + int start_col = 0; + int local_cols_count = 0; + + if (rank < remainder) { + start_col = rank * (cols_per_proc + 1); + local_cols_count = cols_per_proc + 1; + } else { + start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); + local_cols_count = cols_per_proc; + } + + return {start_col, local_cols_count}; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, + int cols, int start_col, int local_cols_count) { + std::vector local_max(local_cols_count, std::numeric_limits::min()); + + for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { + const int global_col = start_col + local_idx; + for (int row = 0; row < rows; ++row) { + const int value = flat_matrix[(row * cols) + global_col]; + local_max[local_idx] = std::max(value, local_max[local_idx]); + } + } + + return local_max; +} + +std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector &local_max, int size, int cols) { + const int cols_per_proc = cols / size; + const int remainder = cols % size; + + std::vector all_max(cols, std::numeric_limits::min()); + std::vector recv_counts(size); + std::vector displs(size); + + for (int ii = 0; ii < size; ++ii) { + recv_counts[ii] = (ii < remainder) ? (cols_per_proc + 1) : cols_per_proc; + displs[ii] = (ii == 0) ? 0 : displs[ii - 1] + recv_counts[ii - 1]; + } + + MPI_Allgatherv(local_max.data(), static_cast(local_max.size()), MPI_INT, all_max.data(), recv_counts.data(), + displs.data(), MPI_INT, MPI_COMM_WORLD); + + return all_max; +} diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index fb0bd344f..44cc7c2f7 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -36,7 +36,6 @@ bool EgorovaLFindMaxValColMatrixSEQ::ValidationImpl() { } const std::size_t cols = matrix[0].size(); - // ЗАМЕНИ цикл на std::ranges::all_of return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; }); } diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 86bd8d132..e1bd2c9c9 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -85,12 +85,16 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = {std::make_tuple(0, "empty_matrix"), +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), std::make_tuple(3, "single_row"), @@ -163,8 +167,9 @@ const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(11, "max_in_first_col"), std::make_tuple(12, "max_in_last_col"), std::make_tuple(13, "zero_values"), - std::make_tuple(14, "many_processes_few_columns"), - std::make_tuple(15, "validation_failure_case")}; + std::make_tuple(14, "single_row_large"), + std::make_tuple(15, "single_column_large"), + std::make_tuple(16, "mixed_positive_negative")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix), From 0057804ac1a87f8d929cbed9d72e16ef70029129 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Thu, 20 Nov 2025 16:39:18 +0000 Subject: [PATCH 21/27] maybe final --- .../report.md | 32 +++++++++---------- .../tests/functional/main.cpp | 7 +--- .../tests/performance/main.cpp | 4 +-- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/report.md b/tasks/egorova_l_find_max_val_col_matrix/report.md index 6f46008eb..eb3cca7ff 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/report.md +++ b/tasks/egorova_l_find_max_val_col_matrix/report.md @@ -5,7 +5,7 @@ - Вариант: 16 ## 1. Введение -Данная лабораторная работа посвящена решению задачи поиска максимальных элементов в столбцах матрицы. Для достижения поставленной цели были разработаны и реализованы два подхода: последовательный алгоритм и параллельная реализация с использованием библиотеки MPI. Основной задачей исследования является сравнительный анализ эффективности данных реализаций и оценка преимуществ параллелизации вычислительного процесса. +Данная лабораторная работа посвящена решению задачи поиска максимальных элементов в столбцах матрицы. Цель работы: разработать и реализовать два подхода последовательный алгоритм и параллельная реализация с использованием библиотеки MPI для решения задачи, а затем сравнить их и сделать выводы. ## 2. Постановка задачи Для заданной матрицы размером M×N необходимо найти вектор максимальных значений для каждого столбца. @@ -54,13 +54,13 @@ for (j от 0 до N-1): ### 4.4 Преимущества и ограничения Преимущества: - минимальные коммуникации (только 2 передачи) -- Идеальная балансировка нагрузки -- Простота реализации -- Масштабируемость +- идеальная балансировка нагрузки +- простота реализации +- масштабируемость Ограничения: -- Каждый процесс хранит полную копию матрицы -- Ограничение по памяти на одном узле +- каждый процесс хранит полную копию матрицы +- ограничение по памяти на одном узле ## 5. Детали реализации @@ -81,7 +81,7 @@ for (j от 0 до N-1): - Тип сборки: Release ### 6.2 Функциональное тестирование -Для проверки корректности реализации проведено комплексное функциональное тестирование, охватывающее различные сценарии работы алгоритма: +Для проверки корректности реализации проведено комплексное функциональное тестирование: Базовые случаи: - Пустая матрица — проверка обработки граничного условия @@ -117,14 +117,14 @@ for (j от 0 до N-1): - Количество запусков: 5 для каждого конфигурации Генерация тестовых данных: -- Используется детерминистический алгоритм заполнения +- Используется алгоритм детерминированного заполнения - Последовательное увеличение значений для предсказуемости результатов - Гарантированное наличие уникальных максимальных значений в каждом столбце Метрики производительности: - Время выполнения (секунды) -- Ускорение (speedup) относительно последовательной версии -- Эффективность параллелизации (efficiency) +- Ускорение относительно последовательной версии +- Эффективность параллелизации - Потребление памяти ## 7. Результаты и обсуждение @@ -157,15 +157,13 @@ for (j от 0 до N-1): ### 7.3 Анализ результатов #### 7.3.1 Влияние размера задачи на производительность -Наблюдается значительное улучшение эффективности параллелизации с ростом размера матрицы: +Проведя тесты стало заметно значительное улучшение эффективности параллелизации с ростом размера матрицы: Для матрицы 5000×5000: - Лучшая эффективность: 55.87% на 2 процессах -- MPI с 1 процессом медленнее sequential версии Для матрицы 10000×10000: - Лучшая эффективность: 61.95% на 2 процессах (+6.08%) -- MPI с 1 процессом быстрее sequential версии - Ускорение улучшилось с 1.12× до 1.24× #### 7.3.2 Оптимальные конфигурации @@ -176,14 +174,14 @@ for (j от 0 до N-1): #### 7.3.3 Динамика масштабируемости Обе размерности демонстрируют схожую динамику: -- Пик эффективности на 2 процессах; -- Резкое снижение эффективности при 4 и более процессах; -- Наилучшее соотношение вычислений и коммуникаций при 2 процессах. +- Пик эффективности на 2 процессах +- Резкое снижение эффективности при 4 и более процессах +- Наилучшее соотношение вычислений и коммуникаций при 2 процессах #### 7.3.4 Выводы по производительности: Алгоритм демонстрирует хорошую масштабируемость для средних и больших размеров задач, что подтверждается ростом эффективности с 55.87% до 61.95% при увеличении размера матрицы. -Оптимальная конфигурация - 2 процесса MPI, что обеспечивает баланс между вычислительной нагрузкой и коммуникационными затратами. +Оптимальная конфигурация — 2 процесса MPI, что обеспечивает баланс между вычислительной нагрузкой и коммуникационными затратами. Ограниченная масштабируемость при большом количестве процессов обусловлена преобладанием коммуникационных операций (MPI_Allgatherv) над вычислительными при распределении на 4 и более процессов. diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index e1bd2c9c9..120b2374e 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -105,22 +105,18 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests expected(matrix[0].size(), std::numeric_limits::min()); for (std::size_t jj = 0; jj < matrix[0].size(); ++jj) { for (std::size_t ii = 0; ii < matrix.size(); ++ii) { @@ -128,7 +124,6 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp index 1f664f57f..66a712aa9 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/performance/main.cpp @@ -13,11 +13,10 @@ namespace egorova_l_find_max_val_col_matrix { class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const std::size_t kMatrixSize_ = 5000; // большая матрица + const std::size_t kMatrixSize_ = 5000; InType input_data_; void SetUp() override { - // Создаем простую детерминированную матрицу input_data_.resize(kMatrixSize_, std::vector(kMatrixSize_)); int counter = 1; @@ -39,7 +38,6 @@ class EgorovaLRunPerfTestProcesses : public ppc::util::BaseRunPerfTests expected(matrix[0].size(), std::numeric_limits::min()); for (size_t jj = 0; jj < matrix[0].size(); ++jj) { for (size_t ii = 0; ii < matrix.size(); ++ii) { From 1a44fc3ad4bdfc7830041b795c90b882f810384b Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Thu, 20 Nov 2025 19:21:28 +0000 Subject: [PATCH 22/27] fix coverage --- .../tests/functional/main.cpp | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 120b2374e..5a6e62947 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -97,6 +97,17 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests kTestParam = {std::make_tuple(0, "empty_matrix"), +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), std::make_tuple(3, "single_row"), @@ -164,7 +173,10 @@ const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(13, "zero_values"), std::make_tuple(14, "single_row_large"), std::make_tuple(15, "single_column_large"), - std::make_tuple(16, "mixed_positive_negative")}; + std::make_tuple(16, "mixed_positive_negative"), + std::make_tuple(17, "empty_matrix_explicit"), + std::make_tuple(18, "zero_cols_matrix"), + std::make_tuple(19, "uneven_column_distribution")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix), From 11220a0412868a27dd77804bd45256b2016ac636 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Thu, 20 Nov 2025 21:44:42 +0000 Subject: [PATCH 23/27] fix2 --- .../tests/functional/main.cpp | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 5a6e62947..90f6a72a8 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -116,6 +116,15 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + int test_type = std::get<0>(test_params); + + // Для некорректной матрицы (test case 20) ожидаем пустой результат + if (test_type == 20) { + return output_data.empty(); + } + // Для пустых матриц ожидаем пустой результат if (matrix.empty() || matrix[0].empty()) { return output_data.empty(); @@ -157,7 +166,7 @@ TEST_P(EgorovaLRunFuncTestsProcesses, FindMaxValColMatrix) { } // тип теста, описание -const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), std::make_tuple(3, "single_row"), @@ -189,6 +198,33 @@ const auto kPerfTestName = EgorovaLRunFuncTestsProcesses::PrintFuncTestName Date: Thu, 20 Nov 2025 23:04:19 +0000 Subject: [PATCH 24/27] fix3 --- .../tests/functional/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index 90f6a72a8..c42c7fd63 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -199,7 +199,7 @@ const auto kPerfTestName = EgorovaLRunFuncTestsProcesses::PrintFuncTestName Date: Fri, 21 Nov 2025 19:46:00 +0000 Subject: [PATCH 25/27] fix cov --- .../info.json | 10 ++-- .../mpi/include/ops_mpi.hpp | 1 - .../mpi/src/ops_mpi.cpp | 42 +++++---------- .../report.md | 43 +++++---------- .../seq/src/ops_seq.cpp | 6 +-- .../tests/functional/main.cpp | 53 ++----------------- 6 files changed, 37 insertions(+), 118 deletions(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/info.json b/tasks/egorova_l_find_max_val_col_matrix/info.json index 2e5f4aa98..56a8132d4 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/info.json +++ b/tasks/egorova_l_find_max_val_col_matrix/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "first_name_p", - "last_name": "last_name_p", - "middle_name": "middle_name_p", - "group_number": "2222222_p", - "task_number": "1" + "first_name": "Егорова", + "last_name": "Лариса", + "middle_name": "Алексеевна", + "group_number": "3823Б1ФИ1", + "task_number": "16" } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp index f671cd0f3..e68b124b0 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp @@ -24,7 +24,6 @@ class EgorovaLFindMaxValColMatrixMPI : public BaseTask { // Объявления вспомогательных методов bool RunMPIAlgorithm(); std::vector CreateAndBroadcastMatrix(int rank, int rows, int cols); - static std::pair CalculateColumnDistribution(int rank, int size, int cols); static std::vector CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, int local_cols_count); static std::vector GatherResults(const std::vector &local_max, int size, int cols); diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index a171be81f..cb70f0aab 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" @@ -47,11 +46,6 @@ bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() { } bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { - if (!ValidationImpl()) { - GetOutput() = std::vector(); - return true; - } - const auto &matrix = GetInput(); if (matrix.empty() || matrix[0].empty()) { @@ -78,13 +72,21 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); - if (rows == 0 || cols == 0) { - GetOutput() = std::vector(); - return true; + std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); + + const int cols_per_proc = cols / size; + const int remainder = cols % size; + int start_col = 0; + int local_cols_count = 0; + + if (rank < remainder) { + start_col = rank * (cols_per_proc + 1); + local_cols_count = cols_per_proc + 1; + } else { + start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); + local_cols_count = cols_per_proc; } - std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); - auto [start_col, local_cols_count] = CalculateColumnDistribution(rank, size, cols); std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); std::vector all_max = GatherResults(local_max, size, cols); @@ -110,24 +112,6 @@ std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int ra return flat_matrix; } -std::pair EgorovaLFindMaxValColMatrixMPI::CalculateColumnDistribution(int rank, int size, int cols) { - const int cols_per_proc = cols / size; - const int remainder = cols % size; - - int start_col = 0; - int local_cols_count = 0; - - if (rank < remainder) { - start_col = rank * (cols_per_proc + 1); - local_cols_count = cols_per_proc + 1; - } else { - start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); - local_cols_count = cols_per_proc; - } - - return {start_col, local_cols_count}; -} - std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, int local_cols_count) { std::vector local_max(local_cols_count, std::numeric_limits::min()); diff --git a/tasks/egorova_l_find_max_val_col_matrix/report.md b/tasks/egorova_l_find_max_val_col_matrix/report.md index eb3cca7ff..fdb83e4e7 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/report.md +++ b/tasks/egorova_l_find_max_val_col_matrix/report.md @@ -208,11 +208,6 @@ for (j от 0 до N-1): ## Приложение ```cpp bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { - if (!ValidationImpl()) { - GetOutput() = std::vector(); - return true; - } - const auto &matrix = GetInput(); if (matrix.empty() || matrix[0].empty()) { @@ -239,13 +234,21 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); - if (rows == 0 || cols == 0) { - GetOutput() = std::vector(); - return true; + std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); + + const int cols_per_proc = cols / size; + const int remainder = cols % size; + int start_col = 0; + int local_cols_count = 0; + + if (rank < remainder) { + start_col = rank * (cols_per_proc + 1); + local_cols_count = cols_per_proc + 1; + } else { + start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); + local_cols_count = cols_per_proc; } - std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); - auto [start_col, local_cols_count] = CalculateColumnDistribution(rank, size, cols); std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); std::vector all_max = GatherResults(local_max, size, cols); @@ -271,24 +274,6 @@ std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int ra return flat_matrix; } -std::pair EgorovaLFindMaxValColMatrixMPI::CalculateColumnDistribution(int rank, int size, int cols) { - const int cols_per_proc = cols / size; - const int remainder = cols % size; - - int start_col = 0; - int local_cols_count = 0; - - if (rank < remainder) { - start_col = rank * (cols_per_proc + 1); - local_cols_count = cols_per_proc + 1; - } else { - start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc); - local_cols_count = cols_per_proc; - } - - return {start_col, local_cols_count}; -} - std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, int local_cols_count) { std::vector local_max(local_cols_count, std::numeric_limits::min()); @@ -321,4 +306,4 @@ std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector displs.data(), MPI_INT, MPI_COMM_WORLD); return all_max; -} +} \ No newline at end of file diff --git a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp index 44cc7c2f7..cd355fe9d 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/seq/src/ops_seq.cpp @@ -46,11 +46,7 @@ bool EgorovaLFindMaxValColMatrixSEQ::PreProcessingImpl() { bool EgorovaLFindMaxValColMatrixSEQ::RunImpl() { const auto &matrix = GetInput(); - if (!ValidationImpl()) { - GetOutput() = std::vector(); - return true; - } - + // Оставляем только проверку на пустоту if (matrix.empty() || matrix[0].empty()) { GetOutput() = std::vector(); return true; diff --git a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp index c42c7fd63..abff18137 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/tests/functional/main.cpp @@ -97,15 +97,8 @@ class EgorovaLRunFuncTestsProcesses : public ppc::util::BaseRunFuncTests(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - int test_type = std::get<0>(test_params); - - // Для некорректной матрицы (test case 20) ожидаем пустой результат - if (test_type == 20) { - return output_data.empty(); - } - // Для пустых матриц ожидаем пустой результат if (matrix.empty() || matrix[0].empty()) { return output_data.empty(); @@ -166,7 +150,7 @@ TEST_P(EgorovaLRunFuncTestsProcesses, FindMaxValColMatrix) { } // тип теста, описание -const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), +const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(1, "zero_matrix"), std::make_tuple(2, "single_column"), std::make_tuple(3, "single_row"), @@ -183,9 +167,7 @@ const std::array kTestParam = {std::make_tuple(0, "empty_matrix"), std::make_tuple(14, "single_row_large"), std::make_tuple(15, "single_column_large"), std::make_tuple(16, "mixed_positive_negative"), - std::make_tuple(17, "empty_matrix_explicit"), - std::make_tuple(18, "zero_cols_matrix"), - std::make_tuple(19, "uneven_column_distribution")}; + std::make_tuple(17, "uneven_column_distribution")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_egorova_l_find_max_val_col_matrix), @@ -198,33 +180,6 @@ const auto kPerfTestName = EgorovaLRunFuncTestsProcesses::PrintFuncTestName Date: Sat, 22 Nov 2025 17:28:21 +0000 Subject: [PATCH 26/27] maybe final 2 --- tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp index e68b124b0..781d82fd3 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp" From e821146751e1d581dca5d84fc780a23b5461d837 Mon Sep 17 00:00:00 2001 From: LarisaEgorova Date: Sun, 30 Nov 2025 12:00:09 +0000 Subject: [PATCH 27/27] fix --- .../data/pic.jpg | Bin 23 -> 0 bytes .../mpi/include/ops_mpi.hpp | 6 +- .../mpi/src/ops_mpi.cpp | 77 +++++++++++++--- .../report.md | 86 +++++++++++++++--- 4 files changed, 138 insertions(+), 31 deletions(-) delete mode 100644 tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg diff --git a/tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg b/tasks/egorova_l_find_max_val_col_matrix/data/pic.jpg deleted file mode 100644 index 637624238c89d914613ed301968bffbf462bc110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY CreateAndBroadcastMatrix(int rank, int rows, int cols); - static std::vector CalculateLocalMaxima(const std::vector &flat_matrix, int rows, int cols, int start_col, + std::vector GetLocalMatrixPart(int rank, int size, int rows, int cols, int start_col, int local_cols_count); + void SendMatrixPartsToOtherRanks(int size, int rows, int cols); + std::vector PrepareMatrixPartForRank(int dest_rank, int size, int rows, int cols); + static std::vector CalculateLocalMaxima(const std::vector &local_matrix_part, int rows, int local_cols_count); static std::vector GatherResults(const std::vector &local_max, int size, int cols); }; diff --git a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp index cb70f0aab..b81fa166e 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp +++ b/tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp @@ -72,8 +72,7 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); - std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); - + // Распределение столбцов по процессам const int cols_per_proc = cols / size; const int remainder = cols % size; int start_col = 0; @@ -87,7 +86,9 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { local_cols_count = cols_per_proc; } - std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); + // Получение локальной части матрицы + std::vector local_matrix_part = GetLocalMatrixPart(rank, size, rows, cols, start_col, local_cols_count); + std::vector local_max = CalculateLocalMaxima(local_matrix_part, rows, local_cols_count); std::vector all_max = GatherResults(local_max, size, cols); GetOutput() = all_max; @@ -95,31 +96,79 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { return true; } -std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int rank, int rows, int cols) { - std::vector flat_matrix(static_cast(rows) * static_cast(cols)); +std::vector EgorovaLFindMaxValColMatrixMPI::GetLocalMatrixPart(int rank, int size, int rows, int cols, + int start_col, int local_cols_count) { + std::vector local_part(static_cast(rows) * static_cast(local_cols_count)); if (rank == 0) { const auto &matrix = GetInput(); + + // Процесс 0 заполняет свою локальную часть for (int ii = 0; ii < rows; ++ii) { - for (int jj = 0; jj < cols; ++jj) { - flat_matrix[(static_cast(ii) * static_cast(cols)) + static_cast(jj)] = - matrix[ii][jj]; + for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { + const int global_col = start_col + local_idx; + local_part[(static_cast(ii) * static_cast(local_cols_count)) + local_idx] = + matrix[ii][global_col]; } } + + // Отправка частей матрицы другим процессам + SendMatrixPartsToOtherRanks(size, rows, cols); + } else { + // Получение данных от процесса 0 + MPI_Recv(local_part.data(), static_cast(local_part.size()), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + + return local_part; +} + +void EgorovaLFindMaxValColMatrixMPI::SendMatrixPartsToOtherRanks(int size, int rows, int cols) { + for (int dest_rank = 1; dest_rank < size; ++dest_rank) { + std::vector dest_part = PrepareMatrixPartForRank(dest_rank, size, rows, cols); + + // Отправка данных процессу-получателю + MPI_Send(dest_part.data(), static_cast(dest_part.size()), MPI_INT, dest_rank, 0, MPI_COMM_WORLD); + } +} + +std::vector EgorovaLFindMaxValColMatrixMPI::PrepareMatrixPartForRank(int dest_rank, int size, int rows, int cols) { + // Вычисление диапазона столбцов для процесса-получателя + const int cols_per_proc = cols / size; + const int remainder = cols % size; + + int dest_start_col = 0; + int dest_cols_count = 0; + + if (dest_rank < remainder) { + dest_start_col = dest_rank * (cols_per_proc + 1); + dest_cols_count = cols_per_proc + 1; + } else { + dest_start_col = (remainder * (cols_per_proc + 1)) + ((dest_rank - remainder) * cols_per_proc); + dest_cols_count = cols_per_proc; + } + + // Подготовка данных для отправки + const auto &matrix = GetInput(); + std::vector dest_part(static_cast(rows) * static_cast(dest_cols_count)); + + for (int ii = 0; ii < rows; ++ii) { + for (int jj = 0; jj < dest_cols_count; ++jj) { + const int global_col = dest_start_col + jj; + dest_part[(static_cast(ii) * static_cast(dest_cols_count)) + jj] = + matrix[ii][global_col]; + } } - MPI_Bcast(flat_matrix.data(), rows * cols, MPI_INT, 0, MPI_COMM_WORLD); - return flat_matrix; + return dest_part; } -std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, - int cols, int start_col, int local_cols_count) { +std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &local_matrix_part, + int rows, int local_cols_count) { std::vector local_max(local_cols_count, std::numeric_limits::min()); for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { - const int global_col = start_col + local_idx; for (int row = 0; row < rows; ++row) { - const int value = flat_matrix[(row * cols) + global_col]; + const int value = local_matrix_part[(row * local_cols_count) + local_idx]; local_max[local_idx] = std::max(value, local_max[local_idx]); } } diff --git a/tasks/egorova_l_find_max_val_col_matrix/report.md b/tasks/egorova_l_find_max_val_col_matrix/report.md index fdb83e4e7..a723e1025 100644 --- a/tasks/egorova_l_find_max_val_col_matrix/report.md +++ b/tasks/egorova_l_find_max_val_col_matrix/report.md @@ -207,6 +207,7 @@ for (j от 0 до N-1): ## Приложение ```cpp +//MPI bool EgorovaLFindMaxValColMatrixMPI::RunImpl() { const auto &matrix = GetInput(); @@ -234,8 +235,7 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); - std::vector flat_matrix = CreateAndBroadcastMatrix(rank, rows, cols); - + // Распределение столбцов по процессам const int cols_per_proc = cols / size; const int remainder = cols % size; int start_col = 0; @@ -249,7 +249,9 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { local_cols_count = cols_per_proc; } - std::vector local_max = CalculateLocalMaxima(flat_matrix, rows, cols, start_col, local_cols_count); + // Получение локальной части матрицы + std::vector local_matrix_part = GetLocalMatrixPart(rank, size, rows, cols, start_col, local_cols_count); + std::vector local_max = CalculateLocalMaxima(local_matrix_part, rows, local_cols_count); std::vector all_max = GatherResults(local_max, size, cols); GetOutput() = all_max; @@ -257,31 +259,79 @@ bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() { return true; } -std::vector EgorovaLFindMaxValColMatrixMPI::CreateAndBroadcastMatrix(int rank, int rows, int cols) { - std::vector flat_matrix(static_cast(rows) * static_cast(cols)); +std::vector EgorovaLFindMaxValColMatrixMPI::GetLocalMatrixPart(int rank, int size, int rows, int cols, + int start_col, int local_cols_count) { + std::vector local_part(static_cast(rows) * static_cast(local_cols_count)); if (rank == 0) { const auto &matrix = GetInput(); + + // Процесс 0 заполняет свою локальную часть for (int ii = 0; ii < rows; ++ii) { - for (int jj = 0; jj < cols; ++jj) { - flat_matrix[(static_cast(ii) * static_cast(cols)) + static_cast(jj)] = - matrix[ii][jj]; + for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { + const int global_col = start_col + local_idx; + local_part[(static_cast(ii) * static_cast(local_cols_count)) + local_idx] = + matrix[ii][global_col]; } } + + // Отправка частей матрицы другим процессам + SendMatrixPartsToOtherRanks(size, rows, cols); + } else { + // Получение данных от процесса 0 + MPI_Recv(local_part.data(), static_cast(local_part.size()), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + + return local_part; +} + +void EgorovaLFindMaxValColMatrixMPI::SendMatrixPartsToOtherRanks(int size, int rows, int cols) { + for (int dest_rank = 1; dest_rank < size; ++dest_rank) { + std::vector dest_part = PrepareMatrixPartForRank(dest_rank, size, rows, cols); + + // Отправка данных процессу-получателю + MPI_Send(dest_part.data(), static_cast(dest_part.size()), MPI_INT, dest_rank, 0, MPI_COMM_WORLD); + } +} + +std::vector EgorovaLFindMaxValColMatrixMPI::PrepareMatrixPartForRank(int dest_rank, int size, int rows, int cols) { + // Вычисление диапазона столбцов для процесса-получателя + const int cols_per_proc = cols / size; + const int remainder = cols % size; + + int dest_start_col = 0; + int dest_cols_count = 0; + + if (dest_rank < remainder) { + dest_start_col = dest_rank * (cols_per_proc + 1); + dest_cols_count = cols_per_proc + 1; + } else { + dest_start_col = (remainder * (cols_per_proc + 1)) + ((dest_rank - remainder) * cols_per_proc); + dest_cols_count = cols_per_proc; + } + + // Подготовка данных для отправки + const auto &matrix = GetInput(); + std::vector dest_part(static_cast(rows) * static_cast(dest_cols_count)); + + for (int ii = 0; ii < rows; ++ii) { + for (int jj = 0; jj < dest_cols_count; ++jj) { + const int global_col = dest_start_col + jj; + dest_part[(static_cast(ii) * static_cast(dest_cols_count)) + jj] = + matrix[ii][global_col]; + } } - MPI_Bcast(flat_matrix.data(), rows * cols, MPI_INT, 0, MPI_COMM_WORLD); - return flat_matrix; + return dest_part; } -std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &flat_matrix, int rows, - int cols, int start_col, int local_cols_count) { +std::vector EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector &local_matrix_part, + int rows, int local_cols_count) { std::vector local_max(local_cols_count, std::numeric_limits::min()); for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) { - const int global_col = start_col + local_idx; for (int row = 0; row < rows; ++row) { - const int value = flat_matrix[(row * cols) + global_col]; + const int value = local_matrix_part[(row * local_cols_count) + local_idx]; local_max[local_idx] = std::max(value, local_max[local_idx]); } } @@ -306,4 +356,10 @@ std::vector EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector displs.data(), MPI_INT, MPI_COMM_WORLD); return all_max; -} \ No newline at end of file +} + +bool EgorovaLFindMaxValColMatrixMPI::PostProcessingImpl() { + return true; +} + +} // namespace egorova_l_find_max_val_col_matrix