From 7113c518a56733dadd2e5849970b16c1d3bacfd8 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Fri, 27 Feb 2026 20:51:34 +0300 Subject: [PATCH 01/30] PeresdachaII --- .../common/include/common.hpp | 17 ++++ .../data/pic.ppm | Bin 0 -> 23 bytes .../info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 25 ++++++ .../mpi/src/ops_mpi.cpp | 73 ++++++++++++++++ .../report.md | 0 .../seq/include/ops_seq.hpp | 22 +++++ .../seq/src/ops_seq.cpp | 32 +++++++ .../settings.json | 7 ++ .../tests/functional/main.cpp | 78 ++++++++++++++++++ .../tests/performance/main.cpp | 58 +++++++++++++ 11 files changed, 321 insertions(+) create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/data/pic.ppm create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/info.json create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/settings.json create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp create mode 100644 tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp new file mode 100644 index 00000000..8a8f525e --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include +#include + +#include "task/include/task.hpp" + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/data/pic.ppm b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/data/pic.ppm new file mode 100644 index 0000000000000000000000000000000000000000..637624238c89d914613ed301968bffbf462bc110 GIT binary patch literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY local_data_; + int rank_; + int size_; +}; + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp new file mode 100644 index 00000000..f1d80dbd --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -0,0 +1,73 @@ +#include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" + +#include + +#include +#include + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +LuchnikovEGenerTransmFromAllToOneGatherMPI::LuchnikovEGenerTransmFromAllToOneGatherMPI(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = OutType(); +} + +bool LuchnikovEGenerTransmFromAllToOneGatherMPI::ValidationImpl() { + MPI_Comm_rank(MPI_COMM_WORLD, &rank_); + MPI_Comm_size(MPI_COMM_WORLD, &size_); + return !GetInput().empty(); +} + +bool LuchnikovEGenerTransmFromAllToOneGatherMPI::PreProcessingImpl() { + MPI_Comm_rank(MPI_COMM_WORLD, &rank_); + MPI_Comm_size(MPI_COMM_WORLD, &size_); + + size_t total_size = GetInput().size(); + size_t base_size = total_size / size_; + size_t remainder = total_size % size_; + + size_t local_start = rank_ * base_size + std::min(static_cast(rank_), remainder); + size_t local_end = local_start + base_size + (static_cast(rank_) < remainder ? 1 : 0); + + local_data_.clear(); + for (size_t i = local_start; i < local_end && i < total_size; ++i) { + local_data_.push_back(GetInput()[i]); + } + + return true; +} + +bool LuchnikovEGenerTransmFromAllToOneGatherMPI::RunImpl() { + std::vector recv_counts(size_); + std::vector displacements(size_); + + int local_size = static_cast(local_data_.size()); + + MPI_Gather(&local_size, 1, MPI_INT, recv_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD); + + if (rank_ == 0) { + displacements[0] = 0; + for (int i = 1; i < size_; ++i) { + displacements[i] = displacements[i - 1] + recv_counts[i - 1]; + } + + int total_size = displacements[size_ - 1] + recv_counts[size_ - 1]; + GetOutput().resize(total_size); + } + + MPI_Gatherv(local_data_.data(), local_size, MPI_INT, GetOutput().data(), recv_counts.data(), displacements.data(), + MPI_INT, 0, MPI_COMM_WORLD); + + MPI_Barrier(MPI_COMM_WORLD); + return true; +} + +bool LuchnikovEGenerTransmFromAllToOneGatherMPI::PostProcessingImpl() { + if (rank_ == 0) { + std::sort(GetOutput().begin(), GetOutput().end()); + } + return true; +} + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md new file mode 100644 index 00000000..e69de29b diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp new file mode 100644 index 00000000..f69959c4 --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +class LuchnikovEGenerTransmFromAllToOneGatherSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit LuchnikovEGenerTransmFromAllToOneGatherSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp new file mode 100644 index 00000000..0f54cabc --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -0,0 +1,32 @@ +#include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" + +#include +#include + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +LuchnikovEGenerTransmFromAllToOneGatherSEQ::LuchnikovEGenerTransmFromAllToOneGatherSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = OutType(); +} + +bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::ValidationImpl() { + return !GetInput().empty(); +} + +bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::PreProcessingImpl() { + GetOutput() = GetInput(); + return true; +} + +bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::RunImpl() { + return true; +} + +bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::PostProcessingImpl() { + std::sort(GetOutput().begin(), GetOutput().end()); + return true; +} + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/settings.json b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/settings.json new file mode 100644 index 00000000..16f25e42 --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/settings.json @@ -0,0 +1,7 @@ +{ + "tasks": { + "mpi": "enabled", + "seq": "enabled" + }, + "tasks_type": "processes" +} diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp new file mode 100644 index 00000000..45cda07b --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -0,0 +1,78 @@ +#include + +#include +#include +#include + +#include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" +#include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" +#include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses + : 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 { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + size_t size = std::get<0>(params); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(1, 100); + + input_data_.resize(size); + for (size_t i = 0; i < size; ++i) { + input_data_[i] = dist(gen); + } + } + + bool CheckTestOutputData(OutType &output_data) final { + OutType expected = input_data_; + std::sort(expected.begin(), expected.end()); + return expected == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; +}; + +namespace { + +TEST_P(LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, GatherTest) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = {std::make_tuple(1, "1"), std::make_tuple(5, "5"), + std::make_tuple(10, "10"), std::make_tuple(20, "20"), + std::make_tuple(50, "50"), std::make_tuple(100, "100"), + std::make_tuple(200, "200"), std::make_tuple(500, "500"), + std::make_tuple(1000, "1000"), std::make_tuple(2000, "2000")}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses::PrintFuncTestName< + LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses>; + +INSTANTIATE_TEST_SUITE_P(AllToGatherTests, LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, kGtestValues, + kPerfTestName); + +} // namespace + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp new file mode 100644 index 00000000..9e12a089 --- /dev/null +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -0,0 +1,58 @@ +#include + +#include +#include + +#include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" +#include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" +#include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace luchnikov_e_gener_transm_from_all_to_one_gather { + +class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::util::BaseRunPerfTests { + const size_t kCount_ = 10000; + InType input_data_{}; + + void SetUp() override { + input_data_.resize(kCount_); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(1, 1000); + + for (size_t i = 0; i < kCount_; ++i) { + input_data_[i] = dist(gen); + } + } + + bool CheckTestOutputData(OutType &output_data) final { + OutType expected = input_data_; + std::sort(expected.begin(), expected.end()); + return expected == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses, RunPerfModes) { + ExecuteTest(GetParam()); +} + +namespace { + +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses, kGtestValues, + kPerfTestName); + +} // namespace + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather From f8e5cf001c4bbc862dd77eb54346582793dc56bb Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 12:39:10 +0300 Subject: [PATCH 02/30] Fix1 --- .../mpi/src/ops_mpi.cpp | 15 ++++++++++----- .../tests/functional/main.cpp | 12 ++++-------- .../tests/performance/main.cpp | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index f1d80dbd..5b10ae58 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -27,12 +27,17 @@ bool LuchnikovEGenerTransmFromAllToOneGatherMPI::PreProcessingImpl() { size_t base_size = total_size / size_; size_t remainder = total_size % size_; - size_t local_start = rank_ * base_size + std::min(static_cast(rank_), remainder); - size_t local_end = local_start + base_size + (static_cast(rank_) < remainder ? 1 : 0); + std::vector send_counts(size_); + std::vector displacements(size_); + + for (int i = 0; i < size_; ++i) { + send_counts[i] = static_cast(base_size + (static_cast(i) < remainder ? 1 : 0)); + displacements[i] = (i == 0) ? 0 : displacements[i - 1] + send_counts[i - 1]; + } - local_data_.clear(); - for (size_t i = local_start; i < local_end && i < total_size; ++i) { - local_data_.push_back(GetInput()[i]); + local_data_.resize(send_counts[rank_]); + for (int i = 0; i < send_counts[rank_]; ++i) { + local_data_[i] = GetInput()[displacements[rank_] + i]; } return true; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 45cda07b..f6f9b7f5 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -42,9 +42,6 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses InType GetTestInputData() final { return input_data_; } - - private: - InType input_data_; }; namespace { @@ -53,11 +50,10 @@ TEST_P(LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, GatherTest) { ExecuteTest(GetParam()); } -const std::array kTestParam = {std::make_tuple(1, "1"), std::make_tuple(5, "5"), - std::make_tuple(10, "10"), std::make_tuple(20, "20"), - std::make_tuple(50, "50"), std::make_tuple(100, "100"), - std::make_tuple(200, "200"), std::make_tuple(500, "500"), - std::make_tuple(1000, "1000"), std::make_tuple(2000, "2000")}; +const std::array kTestParam = { + std::make_tuple(1, "1"), std::make_tuple(2, "2"), std::make_tuple(3, "3"), std::make_tuple(4, "4"), + std::make_tuple(5, "5"), std::make_tuple(6, "6"), std::make_tuple(7, "7"), std::make_tuple(8, "8"), + std::make_tuple(9, "9"), std::make_tuple(10, "10"), std::make_tuple(11, "11"), std::make_tuple(12, "12")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 9e12a089..fbd5f07b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -11,7 +11,7 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const size_t kCount_ = 10000; + const size_t kCount_ = 1000; InType input_data_{}; void SetUp() override { From 0cf6befdbc8b06c51d1500f40960b6ebe161c07f Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 12:55:56 +0300 Subject: [PATCH 03/30] Fix2 --- .../tests/functional/main.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index f6f9b7f5..7352bc32 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -42,6 +42,9 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses InType GetTestInputData() final { return input_data_; } + + private: + InType input_data_; }; namespace { @@ -50,10 +53,10 @@ TEST_P(LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, GatherTest) { ExecuteTest(GetParam()); } -const std::array kTestParam = { - std::make_tuple(1, "1"), std::make_tuple(2, "2"), std::make_tuple(3, "3"), std::make_tuple(4, "4"), - std::make_tuple(5, "5"), std::make_tuple(6, "6"), std::make_tuple(7, "7"), std::make_tuple(8, "8"), - std::make_tuple(9, "9"), std::make_tuple(10, "10"), std::make_tuple(11, "11"), std::make_tuple(12, "12")}; +const std::array kTestParam = { + std::make_tuple(1, "1"), std::make_tuple(2, "2"), std::make_tuple(3, "3"), std::make_tuple(5, "5"), + std::make_tuple(7, "7"), std::make_tuple(10, "10"), std::make_tuple(15, "15"), std::make_tuple(20, "20"), + std::make_tuple(25, "25"), std::make_tuple(30, "30")}; const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( From f7be87a0a1d35078f8a71bb7b4dc8cb10a391d19 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 13:05:44 +0300 Subject: [PATCH 04/30] Fix3 --- .../tests/functional/main.cpp | 7 +++++++ .../tests/performance/main.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 7352bc32..d1dbf6b5 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -34,6 +34,13 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { + if (std::holds_alternative(this->task_->GetTypeOfTask())) { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank != 0) { + return true; + } + } OutType expected = input_data_; std::sort(expected.begin(), expected.end()); return expected == output_data; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index fbd5f07b..ef567cf6 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -26,6 +26,13 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { + if (std::holds_alternative(this->task_->GetTypeOfTask())) { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank != 0) { + return true; + } + } OutType expected = input_data_; std::sort(expected.begin(), expected.end()); return expected == output_data; From b5ea62a7cd76f57c841aa53801afbec1107fc868 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 20:04:25 +0300 Subject: [PATCH 05/30] nowarnigfor2 --- .../tests/functional/main.cpp | 9 ++++++++- .../tests/performance/main.cpp | 15 +++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index d1dbf6b5..f9bf8825 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,7 +1,10 @@ #include +#include #include +#include #include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -34,13 +37,17 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { - if (std::holds_alternative(this->task_->GetTypeOfTask())) { + // Получаем тип задачи через GetTask() + auto task_type = this->GetTask().lock()->GetTypeOfTask(); + + if (task_type == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { return true; } } + OutType expected = input_data_; std::sort(expected.begin(), expected.end()); return expected == output_data; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index ef567cf6..bf160fb4 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -1,6 +1,9 @@ #include +#include +#include #include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -11,28 +14,32 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::util::BaseRunPerfTests { - const size_t kCount_ = 1000; + static constexpr size_t kCount = 1000; // Изменено на static constexpr InType input_data_{}; void SetUp() override { - input_data_.resize(kCount_); + input_data_.resize(kCount); std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution dist(1, 1000); - for (size_t i = 0; i < kCount_; ++i) { + for (size_t i = 0; i < kCount; ++i) { input_data_[i] = dist(gen); } } bool CheckTestOutputData(OutType &output_data) final { - if (std::holds_alternative(this->task_->GetTypeOfTask())) { + // Получаем тип задачи через GetTask() + auto task_type = this->GetTask().lock()->GetTypeOfTask(); + + if (task_type == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { return true; } } + OutType expected = input_data_; std::sort(expected.begin(), expected.end()); return expected == output_data; From 8dfc7c8c178edc5b7ca91c219af116bc04093f77 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 20:13:40 +0300 Subject: [PATCH 06/30] nowarnigfor2 --- .../tests/functional/main.cpp | 1 - .../tests/performance/main.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index f9bf8825..6351e0a7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -37,7 +37,6 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { - // Получаем тип задачи через GetTask() auto task_type = this->GetTask().lock()->GetTypeOfTask(); if (task_type == ppc::task::TypeOfTask::kMPI) { diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index bf160fb4..bb7b6b84 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -14,7 +14,7 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::util::BaseRunPerfTests { - static constexpr size_t kCount = 1000; // Изменено на static constexpr + static constexpr size_t kCount = 1000; InType input_data_{}; void SetUp() override { @@ -29,7 +29,6 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { - // Получаем тип задачи через GetTask() auto task_type = this->GetTask().lock()->GetTypeOfTask(); if (task_type == ppc::task::TypeOfTask::kMPI) { From fc031ee56b734c249e1b2408df4f2c98aae72dee Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 20:16:04 +0300 Subject: [PATCH 07/30] nowarnigfor2 --- .../tests/functional/main.cpp | 5 ++--- .../tests/performance/main.cpp | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 6351e0a7..c58fc6f5 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -37,9 +37,8 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { - auto task_type = this->GetTask().lock()->GetTypeOfTask(); - - if (task_type == ppc::task::TypeOfTask::kMPI) { + // Получаем тип задачи через task_ (он защищенный, а не приватный) + if (this->task_->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index bb7b6b84..b6f96b15 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -29,9 +29,8 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { - auto task_type = this->GetTask().lock()->GetTypeOfTask(); - - if (task_type == ppc::task::TypeOfTask::kMPI) { + // Получаем тип задачи через task_ (он защищенный, а не приватный) + if (this->task_->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { From f5f26fb677d41fed0a6e9a3a908e7cc2ca9509ae Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 20:37:04 +0300 Subject: [PATCH 08/30] nowarnigfor2 --- .../tests/functional/main.cpp | 3 +-- .../tests/performance/main.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index c58fc6f5..8eddd902 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -37,8 +37,7 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { - // Получаем тип задачи через task_ (он защищенный, а не приватный) - if (this->task_->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { + if (this->GetTask()->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index b6f96b15..ab582d88 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -29,8 +29,7 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { - // Получаем тип задачи через task_ (он защищенный, а не приватный) - if (this->task_->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { + if (this->GetTask()->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { From c5cf6332c0b6f2d84b9246ec8b351e82b9dc7ee0 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Sat, 28 Feb 2026 20:52:57 +0300 Subject: [PATCH 09/30] nowarnigfor2 --- .../tests/functional/main.cpp | 3 ++- .../tests/performance/main.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 8eddd902..58b8507b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -37,7 +37,8 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { - if (this->GetTask()->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { + // Проверяем тип задачи через dynamic_cast + if (dynamic_cast(this->GetTaskPtr()) != nullptr) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index ab582d88..07a2b32a 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -29,7 +29,8 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { - if (this->GetTask()->GetTypeOfTask() == ppc::task::TypeOfTask::kMPI) { + // Проверяем тип задачи через dynamic_cast + if (dynamic_cast(this->GetTaskPtr()) != nullptr) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { From 476c0591ea9325cc2b0eb6eb5412844a06e9571c Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 11:55:52 +0300 Subject: [PATCH 10/30] Fix --- .../tests/functional/main.cpp | 8 ++++++-- .../tests/performance/main.cpp | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 58b8507b..f3ae106b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -37,8 +38,11 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses } bool CheckTestOutputData(OutType &output_data) final { + // Получаем указатель на задачу через защищённый метод базового класса + auto* task_ptr = this->GetTask(); + // Проверяем тип задачи через dynamic_cast - if (dynamic_cast(this->GetTaskPtr()) != nullptr) { + if (dynamic_cast(task_ptr) != nullptr) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { @@ -86,4 +90,4 @@ INSTANTIATE_TEST_SUITE_P(AllToGatherTests, LuchnikovEGenerTransmFromAllToOneGath } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 07a2b32a..14ffcf5b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -29,8 +30,11 @@ class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::uti } bool CheckTestOutputData(OutType &output_data) final { + // Получаем указатель на задачу через защищённый метод базового класса + auto *task_ptr = this->GetTask(); + // Проверяем тип задачи через dynamic_cast - if (dynamic_cast(this->GetTaskPtr()) != nullptr) { + if (dynamic_cast(task_ptr) != nullptr) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { From 4e59f8256f174c90820b1bb2d216148ff7519314 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 12:03:08 +0300 Subject: [PATCH 11/30] Fix --- .../seq/include/ops_seq.hpp | 28 +++++++++++++------ .../tests/functional/main.cpp | 8 +++--- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp index f69959c4..83c47bd9 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -1,22 +1,34 @@ #pragma once +#include +#include + #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "task/include/task.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovEGenerTransmFromAllToOneGatherSEQ : public BaseTask { +class LuchnikovEGenerTransmFromAllToOneGatherSequential : public BaseTask { public: - static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { - return ppc::task::TypeOfTask::kSEQ; + static constexpr auto GetStaticTypeOfTask() -> ppc::task::TypeOfTask { + return ppc::task::TypeOfTask::kSequential; } - explicit LuchnikovEGenerTransmFromAllToOneGatherSEQ(const InType &in); + + explicit LuchnikovEGenerTransmFromAllToOneGatherSequential(const InType &input); + + LuchnikovEGenerTransmFromAllToOneGatherSequential(const LuchnikovEGenerTransmFromAllToOneGatherSequential &) = delete; + auto operator=(const LuchnikovEGenerTransmFromAllToOneGatherSequential &) + -> LuchnikovEGenerTransmFromAllToOneGatherSequential & = delete; + LuchnikovEGenerTransmFromAllToOneGatherSequential(LuchnikovEGenerTransmFromAllToOneGatherSequential &&) = delete; + auto operator=(LuchnikovEGenerTransmFromAllToOneGatherSequential &&) + -> LuchnikovEGenerTransmFromAllToOneGatherSequential & = delete; + ~LuchnikovEGenerTransmFromAllToOneGatherSequential() override = default; private: - bool ValidationImpl() override; - bool PreProcessingImpl() override; - bool RunImpl() override; - bool PostProcessingImpl() override; + auto ValidationImpl() -> bool override; + auto PreProcessingImpl() -> bool override; + auto RunImpl() -> bool override; + auto PostProcessingImpl() -> bool override; }; } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index f3ae106b..2fb62061 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -39,10 +39,10 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses bool CheckTestOutputData(OutType &output_data) final { // Получаем указатель на задачу через защищённый метод базового класса - auto* task_ptr = this->GetTask(); - + auto *task_ptr = this->GetTask(); + // Проверяем тип задачи через dynamic_cast - if (dynamic_cast(task_ptr) != nullptr) { + if (dynamic_cast(task_ptr) != nullptr) { int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != 0) { @@ -90,4 +90,4 @@ INSTANTIATE_TEST_SUITE_P(AllToGatherTests, LuchnikovEGenerTransmFromAllToOneGath } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 04ecff6d2ab501ac2ec45064f5f593f5807a5c6e Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 12:19:37 +0300 Subject: [PATCH 12/30] Fix --- .../common/include/common.hpp | 16 +- .../mpi/include/ops_mpi.hpp | 8 +- .../mpi/src/ops_mpi.cpp | 217 +++++++++-- .../seq/include/ops_seq.hpp | 28 +- .../seq/src/ops_seq.cpp | 60 +++- .../tests/functional/main.cpp | 336 ++++++++++++++++-- .../tests/performance/main.cpp | 103 ++++-- 7 files changed, 625 insertions(+), 143 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp index 8a8f525e..d72b7006 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp @@ -1,6 +1,7 @@ #pragma once -#include +#include + #include #include #include @@ -9,9 +10,16 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -using InType = std::vector; -using OutType = std::vector; -using TestType = std::tuple; +struct GatherInput { + std::vector data; + int count{0}; + MPI_Datatype datatype{MPI_DATATYPE_NULL}; + int root{0}; +}; + +using InType = GatherInput; +using OutType = std::vector; +using TestType = std::tuple; using BaseTask = ppc::task::Task; } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp index 22d5fa27..3f448aca 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp @@ -5,21 +5,19 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovEGenerTransmFromAllToOneGatherMPI : public BaseTask { +class LuchnikovETransmFrAllToOneGatherMPI : public BaseTask { public: static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { return ppc::task::TypeOfTask::kMPI; } - explicit LuchnikovEGenerTransmFromAllToOneGatherMPI(const InType &in); + + explicit LuchnikovETransmFrAllToOneGatherMPI(const InType &in); private: bool ValidationImpl() override; bool PreProcessingImpl() override; bool RunImpl() override; bool PostProcessingImpl() override; - std::vector local_data_; - int rank_; - int size_; }; } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 5b10ae58..687fe33c 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -3,75 +3,214 @@ #include #include +#include +#include +#include +#include #include +#include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" + namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransmFromAllToOneGatherMPI::LuchnikovEGenerTransmFromAllToOneGatherMPI(const InType &in) { +namespace { +int GetTypeSize(MPI_Datatype datatype) { + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } + return 0; +} + +bool IsPowerOfTwo(int x) { + return (x > 0) && ((x & (x - 1)) == 0); +} + +int NextPowerOfTwo(int x) { + int power = 1; + while (power < x) { + power <<= 1; + } + return power; +} +} // namespace + +LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = OutType(); } -bool LuchnikovEGenerTransmFromAllToOneGatherMPI::ValidationImpl() { - MPI_Comm_rank(MPI_COMM_WORLD, &rank_); - MPI_Comm_size(MPI_COMM_WORLD, &size_); - return !GetInput().empty(); -} +bool LuchnikovETransmFrAllToOneGatherMPI::ValidationImpl() { + const auto &input = GetInput(); -bool LuchnikovEGenerTransmFromAllToOneGatherMPI::PreProcessingImpl() { - MPI_Comm_rank(MPI_COMM_WORLD, &rank_); - MPI_Comm_size(MPI_COMM_WORLD, &size_); + if (input.count <= 0) { + return false; + } - size_t total_size = GetInput().size(); - size_t base_size = total_size / size_; - size_t remainder = total_size % size_; + if (input.datatype != MPI_INT && input.datatype != MPI_FLOAT && input.datatype != MPI_DOUBLE) { + return false; + } - std::vector send_counts(size_); - std::vector displacements(size_); + if (input.root < 0) { + return false; + } - for (int i = 0; i < size_; ++i) { - send_counts[i] = static_cast(base_size + (static_cast(i) < remainder ? 1 : 0)); - displacements[i] = (i == 0) ? 0 : displacements[i - 1] + send_counts[i - 1]; + const int type_size = GetTypeSize(input.datatype); + if (type_size <= 0) { + return false; } - local_data_.resize(send_counts[rank_]); - for (int i = 0; i < send_counts[rank_]; ++i) { - local_data_[i] = GetInput()[displacements[rank_] + i]; + const size_t expected_size = static_cast(input.count) * static_cast(type_size); + + if (input.data.size() != expected_size) { + return false; } + int size = 1; + MPI_Comm_size(MPI_COMM_WORLD, &size); + + return input.root < size; +} + +bool LuchnikovETransmFrAllToOneGatherMPI::PreProcessingImpl() { return true; } -bool LuchnikovEGenerTransmFromAllToOneGatherMPI::RunImpl() { - std::vector recv_counts(size_); - std::vector displacements(size_); +bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { + int rank = 0; + int world_size = 1; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + const auto &input = GetInput(); + const int type_size = GetTypeSize(input.datatype); + const int block_size = input.count * type_size; + + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm temp_comm = MPI_COMM_COMM_WORLD; + int actual_size = world_size; + int actual_rank = rank; + + if (!IsPowerOfTwo(world_size)) { + int next_power = NextPowerOfTwo(world_size); + std::vector ranks(next_power); + for (int i = 0; i < next_power; ++i) { + ranks[i] = i % world_size; + } + + MPI_Group world_group, new_group; + MPI_Comm_group(MPI_COMM_WORLD, &world_group); + MPI_Group_incl(world_group, next_power, ranks.data(), &new_group); + MPI_Comm_create(MPI_COMM_WORLD, new_group, &temp_comm); + MPI_Group_free(&world_group); + MPI_Group_free(&new_group); + + if (temp_comm != MPI_COMM_NULL) { + comm = temp_comm; + MPI_Comm_rank(comm, &actual_rank); + MPI_Comm_size(comm, &actual_size); + } + } - int local_size = static_cast(local_data_.size()); + std::vector send_buffer(block_size); + std::copy(input.data.begin(), input.data.end(), send_buffer.begin()); - MPI_Gather(&local_size, 1, MPI_INT, recv_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD); + std::vector recv_buffer; + if (rank == input.root) { + recv_buffer.resize(static_cast(actual_size) * static_cast(block_size)); + } + + int step = 1; + while (step < actual_size) { + if (actual_rank % (2 * step) == 0) { + int source = actual_rank + step; + if (source < actual_size) { + int source_rank = source; + if (!IsPowerOfTwo(world_size)) { + source_rank = source % world_size; + } + + int recv_size = step * block_size; + std::vector temp_recv(recv_size); + MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); + } + } else { + int dest = actual_rank - step; + int dest_rank = dest; + if (!IsPowerOfTwo(world_size)) { + dest_rank = dest % world_size; + } + + MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest_rank, 0, MPI_COMM_WORLD); + break; + } + step *= 2; + } - if (rank_ == 0) { - displacements[0] = 0; - for (int i = 1; i < size_; ++i) { - displacements[i] = displacements[i - 1] + recv_counts[i - 1]; + if (rank == input.root) { + auto *out_ptr = recv_buffer.data(); + + for (int i = 0; i < actual_size; ++i) { + int source_rank = i; + if (!IsPowerOfTwo(world_size)) { + source_rank = i % world_size; + } + + if (source_rank == rank) { + std::copy(send_buffer.begin(), send_buffer.begin() + block_size, out_ptr + i * block_size); + } else { + bool found = false; + for (size_t j = block_size; j < send_buffer.size(); j += block_size) { + if (j / block_size == static_cast(i)) { + std::copy(send_buffer.begin() + static_cast(j), + send_buffer.begin() + static_cast(j + block_size), out_ptr + i * block_size); + found = true; + break; + } + } + + if (!found && i < world_size) { + std::vector direct_recv(block_size); + MPI_Recv(direct_recv.data(), block_size, MPI_BYTE, source_rank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + std::copy(direct_recv.begin(), direct_recv.end(), out_ptr + i * block_size); + } + } } - int total_size = displacements[size_ - 1] + recv_counts[size_ - 1]; - GetOutput().resize(total_size); + GetOutput() = std::move(recv_buffer); + } else { + bool sent = false; + int temp_rank = actual_rank; + while (temp_rank % 2 == 0 && temp_rank > 0) { + temp_rank /= 2; + } + + if (temp_rank > 0) { + sent = true; + } + + if (!sent && rank < world_size) { + MPI_Send(send_buffer.data(), block_size, MPI_BYTE, input.root, 1, MPI_COMM_WORLD); + } + + GetOutput() = std::vector(); } - MPI_Gatherv(local_data_.data(), local_size, MPI_INT, GetOutput().data(), recv_counts.data(), displacements.data(), - MPI_INT, 0, MPI_COMM_WORLD); + if (temp_comm != MPI_COMM_WORLD && temp_comm != MPI_COMM_COMM_WORLD && temp_comm != MPI_COMM_NULL) { + MPI_Comm_free(&temp_comm); + } - MPI_Barrier(MPI_COMM_WORLD); return true; } -bool LuchnikovEGenerTransmFromAllToOneGatherMPI::PostProcessingImpl() { - if (rank_ == 0) { - std::sort(GetOutput().begin(), GetOutput().end()); - } +bool LuchnikovETransmFrAllToOneGatherMPI::PostProcessingImpl() { return true; } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp index 83c47bd9..aec5c451 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -1,34 +1,22 @@ #pragma once -#include -#include - #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "task/include/task.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovEGenerTransmFromAllToOneGatherSequential : public BaseTask { +class LuchnikovETransmFrAllToOneGatherSEQ : public BaseTask { public: - static constexpr auto GetStaticTypeOfTask() -> ppc::task::TypeOfTask { - return ppc::task::TypeOfTask::kSequential; + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; } - - explicit LuchnikovEGenerTransmFromAllToOneGatherSequential(const InType &input); - - LuchnikovEGenerTransmFromAllToOneGatherSequential(const LuchnikovEGenerTransmFromAllToOneGatherSequential &) = delete; - auto operator=(const LuchnikovEGenerTransmFromAllToOneGatherSequential &) - -> LuchnikovEGenerTransmFromAllToOneGatherSequential & = delete; - LuchnikovEGenerTransmFromAllToOneGatherSequential(LuchnikovEGenerTransmFromAllToOneGatherSequential &&) = delete; - auto operator=(LuchnikovEGenerTransmFromAllToOneGatherSequential &&) - -> LuchnikovEGenerTransmFromAllToOneGatherSequential & = delete; - ~LuchnikovEGenerTransmFromAllToOneGatherSequential() override = default; + explicit LuchnikovETransmFrAllToOneGatherSEQ(const InType &in); private: - auto ValidationImpl() -> bool override; - auto PreProcessingImpl() -> bool override; - auto RunImpl() -> bool override; - auto PostProcessingImpl() -> bool override; + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; }; } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index 0f54cabc..33aefcf1 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -1,31 +1,71 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" -#include +#include + +#include #include +#include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" + namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransmFromAllToOneGatherSEQ::LuchnikovEGenerTransmFromAllToOneGatherSEQ(const InType &in) { +namespace { +size_t GetTypeSizeSeq(MPI_Datatype datatype) { + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } + return 0; +} +} // namespace + +LuchnikovETransmFrAllToOneGatherSEQ::LuchnikovETransmFrAllToOneGatherSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = OutType(); } -bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::ValidationImpl() { - return !GetInput().empty(); +bool LuchnikovETransmFrAllToOneGatherSEQ::ValidationImpl() { + const auto &input = GetInput(); + + if (input.count <= 0) { + return false; + } + + if (input.root < 0) { + return false; + } + + size_t type_size = GetTypeSizeSeq(input.datatype); + + if (type_size == 0) { + return false; + } + + if (input.data.size() != static_cast(input.count) * type_size) { + return false; + } + + return true; } -bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::PreProcessingImpl() { - GetOutput() = GetInput(); +bool LuchnikovETransmFrAllToOneGatherSEQ::PreProcessingImpl() { return true; } -bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::RunImpl() { +bool LuchnikovETransmFrAllToOneGatherSEQ::RunImpl() { + const auto &input = GetInput(); + + GetOutput() = input.data; + return true; } -bool LuchnikovEGenerTransmFromAllToOneGatherSEQ::PostProcessingImpl() { - std::sort(GetOutput().begin(), GetOutput().end()); +bool LuchnikovETransmFrAllToOneGatherSEQ::PostProcessingImpl() { return true; } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 2fb62061..240f69eb 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -2,10 +2,10 @@ #include #include +#include #include -#include -#include #include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -15,44 +15,125 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses - : public ppc::util::BaseRunFuncTests { +class LuchnikovETransmFrAllToOneGatherFuncTests : 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); + const auto &count = std::get<0>(test_param); + const auto &root = std::get<1>(test_param); + const auto &datatype = std::get<2>(test_param); + const auto &name = std::get<3>(test_param); + + std::string type_str; + if (datatype == MPI_INT) { + type_str = "int"; + } else if (datatype == MPI_FLOAT) { + type_str = "float"; + } else if (datatype == MPI_DOUBLE) { + type_str = "double"; + } + + return "count" + std::to_string(count) + "_root" + std::to_string(root) + "_" + type_str + "_" + name; } protected: void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - size_t size = std::get<0>(params); + TestType params = std::get<2>(GetParam()); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dist(1, 100); + const auto &count = std::get<0>(params); + const auto &root = std::get<1>(params); + const auto &datatype = std::get<2>(params); - input_data_.resize(size); - for (size_t i = 0; i < size; ++i) { - input_data_[i] = dist(gen); + int type_size = 0; + if (datatype == MPI_INT) { + type_size = sizeof(int); + } else if (datatype == MPI_FLOAT) { + type_size = sizeof(float); + } else if (datatype == MPI_DOUBLE) { + type_size = sizeof(double); } + + size_t total_size = static_cast(count) * static_cast(type_size); + std::vector data(total_size); + + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (datatype == MPI_INT) { + auto *data_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + data_ptr[i] = rank * count + i + 1; + } + } else if (datatype == MPI_FLOAT) { + auto *data_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + data_ptr[i] = static_cast(rank * count + i) + 0.5F; + } + } else if (datatype == MPI_DOUBLE) { + auto *data_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + data_ptr[i] = static_cast(rank * count + i) + 0.25; + } + } + + input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; + } + + static int GetTypeSize(MPI_Datatype datatype) { + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } + return 0; } bool CheckTestOutputData(OutType &output_data) final { - // Получаем указатель на задачу через защищённый метод базового класса - auto *task_ptr = this->GetTask(); + const auto &input = input_data_; + const auto ¶ms = std::get<2>(GetParam()); + const std::string test_name = std::get<3>(params); + bool is_mpi = test_name.find("_mpi_") != std::string::npos; - // Проверяем тип задачи через dynamic_cast - if (dynamic_cast(task_ptr) != nullptr) { - int rank = 0; + int world_size = 1; + int rank = 0; + if (is_mpi) { + MPI_Comm_size(MPI_COMM_WORLD, &world_size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != 0) { + if (rank != input.root) { return true; } } - OutType expected = input_data_; - std::sort(expected.begin(), expected.end()); - return expected == output_data; + if (output_data.empty()) { + return false; + } + + const auto type_size = static_cast(GetTypeSize(input.datatype)); + const size_t expected_size = static_cast(input.count) * static_cast(world_size) * type_size; + + if (output_data.size() != expected_size) { + return false; + } + + if (rank == input.root) { + if (input.datatype == MPI_INT) { + const int *out_ptr = reinterpret_cast(output_data.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < input.count; ++j) { + int expected_value = i * input.count + j + 1; + int actual_value = out_ptr[i * input.count + j]; + if (actual_value != expected_value) { + return false; + } + } + } + } + } + + return true; } InType GetTestInputData() final { @@ -65,28 +146,217 @@ class LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses namespace { -TEST_P(LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, GatherTest) { +TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { ExecuteTest(GetParam()); } -const std::array kTestParam = { - std::make_tuple(1, "1"), std::make_tuple(2, "2"), std::make_tuple(3, "3"), std::make_tuple(5, "5"), - std::make_tuple(7, "7"), std::make_tuple(10, "10"), std::make_tuple(15, "15"), std::make_tuple(20, "20"), - std::make_tuple(25, "25"), std::make_tuple(30, "30")}; +const std::array kTestParam = {std::make_tuple(1, 0, MPI_INT, "SingleElementIntRoot0"), + std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), + std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), + std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0"), + std::make_tuple(2, 1, MPI_INT, "IntRoot1"), + std::make_tuple(2, 2, MPI_INT, "IntRoot2")}; const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask( + std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( + ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); -const auto kPerfTestName = LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses::PrintFuncTestName< - LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses>; +const auto kPerfTestName = + LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, kGtestValues, kPerfTestName); + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { + int rank = 0; + int world_size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + int count = 3; + std::vector data(count * sizeof(int)); + auto *data_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + data_ptr[i] = rank * count + i + 1; + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + EXPECT_TRUE(task.Validation()); + EXPECT_TRUE(task.PreProcessing()); + EXPECT_TRUE(task.Run()); + EXPECT_TRUE(task.PostProcessing()); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_FALSE(result.empty()); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); + + const int *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + EXPECT_EQ(res_ptr[i * count + j], i * count + j + 1); + } + } + } +} + +TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { + int count = 3; + std::vector data(count * sizeof(int)); + auto *data_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + data_ptr[i] = i + 1; + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherSEQ task(input); + + EXPECT_TRUE(task.Validation()); + EXPECT_TRUE(task.PreProcessing()); + EXPECT_TRUE(task.Run()); + EXPECT_TRUE(task.PostProcessing()); + + const auto &result = task.GetOutput(); + ASSERT_EQ(result.size(), static_cast(count) * sizeof(int)); -INSTANTIATE_TEST_SUITE_P(AllToGatherTests, LuchnikovEGenerTransmFromAllToOneGatherFuncTestsProcesses, kGtestValues, - kPerfTestName); + const int *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(res_ptr[i], i + 1); + } +} + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { + int world_size = 1; + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + std::vector data(sizeof(int)); + + GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); + EXPECT_FALSE(task_1.Validation()); + + GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = world_size}; + LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); + EXPECT_FALSE(task_2.Validation()); + + GatherInput input_wrong_type{.data = data, .count = 1, .datatype = MPI_CHAR, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); + EXPECT_FALSE(task_3.Validation()); + + std::vector wrong_size_data(sizeof(int) * 2); + GatherInput input_wrong_size{.data = wrong_size_data, .count = 1, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task_4(input_wrong_size); + EXPECT_FALSE(task_4.Validation()); +} + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { + int rank = 0; + int world_size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + int root = world_size / 2; + int count = 2; + std::vector data(static_cast(count) * sizeof(float)); + auto *d_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + d_ptr[i] = static_cast(rank * count + i); + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + ASSERT_TRUE(task.Validation()); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == root) { + const auto &result = task.GetOutput(); + ASSERT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(float)); + const auto *res_ptr = reinterpret_cast(result.data()); + for (int rank_id = 0; rank_id < world_size; ++rank_id) { + for (int i = 0; i < count; ++i) { + EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast(rank_id * count + i)); + } + } + } +} + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { + int rank = 0; + int world_size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + int count = 1000; + std::vector data(static_cast(count) * sizeof(double)); + auto *d_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + d_ptr[i] = static_cast(rank * count + i); + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + ASSERT_TRUE(task.Validation()); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(double)); + + const double *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + EXPECT_DOUBLE_EQ(res_ptr[i * count + j], static_cast(i * count + j)); + } + } + } +} + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { + int rank = 0; + int world_size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + if (world_size > 3 && !((world_size & (world_size - 1)) == 0)) { + int count = 3; + std::vector data(static_cast(count) * sizeof(int)); + auto *d_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + d_ptr[i] = rank * count + i; + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + ASSERT_TRUE(task.Validation()); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); + + const int *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + EXPECT_EQ(res_ptr[i * count + j], i * count + j); + } + } + } + } +} } // namespace diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 14ffcf5b..c7642967 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include @@ -14,61 +12,102 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses : public ppc::util::BaseRunPerfTests { - static constexpr size_t kCount = 1000; - InType input_data_{}; +namespace { +size_t GetTypeSizeSeq(MPI_Datatype datatype) { + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } + return 0; +} +} // namespace + +class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { + protected: + static const size_t kDataCount = 100000; + MPI_Datatype data_type = MPI_INT; + + InType input_data{}; void SetUp() override { - input_data_.resize(kCount); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dist(1, 1000); + const size_t type_size = sizeof(int); + std::vector data(kDataCount * type_size); + + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); - for (size_t i = 0; i < kCount; ++i) { - input_data_[i] = dist(gen); + auto *data_ptr = reinterpret_cast(data.data()); + for (size_t i = 0; i < kDataCount; ++i) { + data_ptr[i] = static_cast((static_cast(rank) * kDataCount) + i); } + + const int root = 0; + input_data = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; } bool CheckTestOutputData(OutType &output_data) final { - // Получаем указатель на задачу через защищённый метод базового класса - auto *task_ptr = this->GetTask(); + const auto &input = input_data; + + const auto ¶ms = GetParam(); + const std::string task_name = std::get<1>(params); + const bool is_mpi = task_name.find("_mpi_") != std::string::npos; - // Проверяем тип задачи через dynamic_cast - if (dynamic_cast(task_ptr) != nullptr) { - int rank = 0; + int world_size = 1; + int rank = 0; + if (is_mpi) { + MPI_Comm_size(MPI_COMM_WORLD, &world_size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != 0) { + if (rank != input.root) { return true; } } - OutType expected = input_data_; - std::sort(expected.begin(), expected.end()); - return expected == output_data; + const size_t type_size = GetTypeSizeSeq(input.datatype); + const size_t expected_size = static_cast(input.count) * static_cast(world_size) * type_size; + + if (output_data.size() != expected_size) { + return false; + } + + // Дополнительная проверка корректности данных для перформанс тестов + if (rank == input.root && input.datatype == MPI_INT) { + const int *out_ptr = reinterpret_cast(output_data.data()); + for (int i = 0; i < world_size; ++i) { + for (size_t j = 0; j < kDataCount; ++j) { + int expected = static_cast(i * static_cast(kDataCount) + static_cast(j)); + int actual = out_ptr[i * static_cast(kDataCount) + static_cast(j)]; + if (actual != expected) { + return false; + } + } + } + } + + return true; } InType GetTestInputData() final { - return input_data_; + return input_data; } }; -TEST_P(LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses, RunPerfModes) { +TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { ExecuteTest(GetParam()); } -namespace { - -const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); -const auto kPerfTestName = LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses::CustomPerfTestName; +const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; -INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovEGenerTransmFromAllToOneGatherPerfTestProcesses, kGtestValues, - kPerfTestName); - -} // namespace +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From b83fc51a03d5c6f9bd630885f631e8d33f3c2cee Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 12:28:01 +0300 Subject: [PATCH 13/30] Fix --- .../mpi/src/ops_mpi.cpp | 134 ++++++------------ .../tests/functional/main.cpp | 88 +++++++----- .../tests/performance/main.cpp | 71 +++++++--- 3 files changed, 150 insertions(+), 143 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 687fe33c..4ca563c7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -91,122 +91,80 @@ bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { const int type_size = GetTypeSize(input.datatype); const int block_size = input.count * type_size; - MPI_Comm comm = MPI_COMM_WORLD; - MPI_Comm temp_comm = MPI_COMM_COMM_WORLD; - int actual_size = world_size; - int actual_rank = rank; - + // Для нестепени двойки используем простой алгоритм с прямыми передачами if (!IsPowerOfTwo(world_size)) { - int next_power = NextPowerOfTwo(world_size); - std::vector ranks(next_power); - for (int i = 0; i < next_power; ++i) { - ranks[i] = i % world_size; - } + if (rank == input.root) { + // Корневой процесс собирает данные от всех + std::vector recv_buffer(static_cast(world_size) * static_cast(block_size)); + + // Копируем свои данные + std::copy(input.data.begin(), input.data.end(), + recv_buffer.begin() + static_cast(rank * block_size)); + + // Получаем данные от всех остальных процессов + for (int i = 0; i < world_size; ++i) { + if (i != rank) { + MPI_Recv(recv_buffer.data() + i * block_size, block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + } - MPI_Group world_group, new_group; - MPI_Comm_group(MPI_COMM_WORLD, &world_group); - MPI_Group_incl(world_group, next_power, ranks.data(), &new_group); - MPI_Comm_create(MPI_COMM_WORLD, new_group, &temp_comm); - MPI_Group_free(&world_group); - MPI_Group_free(&new_group); - - if (temp_comm != MPI_COMM_NULL) { - comm = temp_comm; - MPI_Comm_rank(comm, &actual_rank); - MPI_Comm_size(comm, &actual_size); + GetOutput() = std::move(recv_buffer); + } else { + // Некорневые процессы отправляют свои данные корню + MPI_Send(input.data.data(), block_size, MPI_BYTE, input.root, 0, MPI_COMM_WORLD); + GetOutput() = std::vector(); } + + return true; } + // Для степени двойки используем древовидный алгоритм std::vector send_buffer(block_size); std::copy(input.data.begin(), input.data.end(), send_buffer.begin()); std::vector recv_buffer; if (rank == input.root) { - recv_buffer.resize(static_cast(actual_size) * static_cast(block_size)); + recv_buffer.resize(static_cast(world_size) * static_cast(block_size)); + // Копируем свои данные в начало буфера + std::copy(send_buffer.begin(), send_buffer.end(), recv_buffer.begin()); } + // Древовидный сбор данных int step = 1; - while (step < actual_size) { - if (actual_rank % (2 * step) == 0) { - int source = actual_rank + step; - if (source < actual_size) { - int source_rank = source; - if (!IsPowerOfTwo(world_size)) { - source_rank = source % world_size; - } - + while (step < world_size) { + if (rank % (2 * step) == 0) { + // Принимаем данные от процессов с шагом step + int source = rank + step; + if (source < world_size) { int recv_size = step * block_size; std::vector temp_recv(recv_size); - MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - - send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); + MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + // Вставляем полученные данные в правильную позицию + if (rank == input.root) { + // Корень сразу сохраняет в финальный буфер + std::copy(temp_recv.begin(), temp_recv.end(), + recv_buffer.begin() + static_cast(source * block_size)); + } else { + // Промежуточные узлы накапливают данные для отправки выше + send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); + } } } else { - int dest = actual_rank - step; - int dest_rank = dest; - if (!IsPowerOfTwo(world_size)) { - dest_rank = dest % world_size; - } - - MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest_rank, 0, MPI_COMM_WORLD); + // Отправляем данные родительскому процессу + int dest = rank - step; + MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest, 0, MPI_COMM_WORLD); break; } step *= 2; } if (rank == input.root) { - auto *out_ptr = recv_buffer.data(); - - for (int i = 0; i < actual_size; ++i) { - int source_rank = i; - if (!IsPowerOfTwo(world_size)) { - source_rank = i % world_size; - } - - if (source_rank == rank) { - std::copy(send_buffer.begin(), send_buffer.begin() + block_size, out_ptr + i * block_size); - } else { - bool found = false; - for (size_t j = block_size; j < send_buffer.size(); j += block_size) { - if (j / block_size == static_cast(i)) { - std::copy(send_buffer.begin() + static_cast(j), - send_buffer.begin() + static_cast(j + block_size), out_ptr + i * block_size); - found = true; - break; - } - } - - if (!found && i < world_size) { - std::vector direct_recv(block_size); - MPI_Recv(direct_recv.data(), block_size, MPI_BYTE, source_rank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - std::copy(direct_recv.begin(), direct_recv.end(), out_ptr + i * block_size); - } - } - } - GetOutput() = std::move(recv_buffer); } else { - bool sent = false; - int temp_rank = actual_rank; - while (temp_rank % 2 == 0 && temp_rank > 0) { - temp_rank /= 2; - } - - if (temp_rank > 0) { - sent = true; - } - - if (!sent && rank < world_size) { - MPI_Send(send_buffer.data(), block_size, MPI_BYTE, input.root, 1, MPI_COMM_WORLD); - } - GetOutput() = std::vector(); } - if (temp_comm != MPI_COMM_WORLD && temp_comm != MPI_COMM_COMM_WORLD && temp_comm != MPI_COMM_NULL) { - MPI_Comm_free(&temp_comm); - } - return true; } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 240f69eb..3614fd69 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -11,30 +11,11 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" -#include "util/include/func_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncTests { - public: - static std::string PrintTestParam(const TestType &test_param) { - const auto &count = std::get<0>(test_param); - const auto &root = std::get<1>(test_param); - const auto &datatype = std::get<2>(test_param); - const auto &name = std::get<3>(test_param); - - std::string type_str; - if (datatype == MPI_INT) { - type_str = "int"; - } else if (datatype == MPI_FLOAT) { - type_str = "float"; - } else if (datatype == MPI_DOUBLE) { - type_str = "double"; - } - - return "count" + std::to_string(count) + "_root" + std::to_string(root) + "_" + type_str + "_" + name; - } - +class LuchnikovETransmFrAllToOneGatherFuncTests + : public ::testing::TestWithParam> { protected: void SetUp() override { TestType params = std::get<2>(GetParam()); @@ -91,11 +72,11 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT return 0; } - bool CheckTestOutputData(OutType &output_data) final { + bool CheckOutputData(OutType &output_data) { const auto &input = input_data_; const auto ¶ms = std::get<2>(GetParam()); - const std::string test_name = std::get<3>(params); - bool is_mpi = test_name.find("_mpi_") != std::string::npos; + const std::string test_name = std::get<1>(GetParam()); + bool is_mpi = test_name.find("MPI") != std::string::npos; int world_size = 1; int rank = 0; @@ -136,18 +117,43 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT return true; } - InType GetTestInputData() final { + GatherInput GetInputData() { return input_data_; } + void ExecuteTest() { + const auto ¶ms = GetParam(); + const std::string task_type = std::get<1>(params); + + if (task_type.find("MPI") != std::string::npos) { + LuchnikovETransmFrAllToOneGatherMPI task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } else { + LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } + } + private: - InType input_data_; + GatherInput input_data_; }; namespace { TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { - ExecuteTest(GetParam()); + ExecuteTest(); } const std::array kTestParam = {std::make_tuple(1, 0, MPI_INT, "SingleElementIntRoot0"), @@ -157,18 +163,24 @@ const std::array kTestParam = {std::make_tuple(1, 0, MPI_INT, "Sing std::make_tuple(2, 1, MPI_INT, "IntRoot1"), std::make_tuple(2, 2, MPI_INT, "IntRoot2")}; -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask( - kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( - kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); +std::vector> CreateTestParams() { + std::vector> params; -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + for (const auto &test_case : kTestParam) { + params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", test_case)); -const auto kPerfTestName = - LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; + params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", test_case)); + } -INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, kGtestValues, kPerfTestName); + return params; +} + +INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, + ::testing::ValuesIn(CreateTestParams()), + [](const testing::TestParamInfo &info) { + std::string name = std::get<1>(info.param) + "_" + std::get<3>(std::get<2>(info.param)); + return name; + }); TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int rank = 0; @@ -328,7 +340,9 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); - if (world_size > 3 && !((world_size & (world_size - 1)) == 0)) { + bool is_power_of_two = (world_size > 0) && ((world_size & (world_size - 1)) == 0); + + if (!is_power_of_two && world_size > 3) { int count = 3; std::vector data(static_cast(count) * sizeof(int)); auto *d_ptr = reinterpret_cast(data.data()); diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index c7642967..43b2472e 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -8,7 +8,6 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" -#include "util/include/perf_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { @@ -25,15 +24,18 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { } return 0; } + +std::string GetTaskName(const std::tuple ¶m) { + return std::get<1>(param); +} } // namespace -class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { +class LuchnikovETransmFrAllToOneGatherPerfTests + : public ::testing::TestWithParam> { protected: static const size_t kDataCount = 100000; MPI_Datatype data_type = MPI_INT; - InType input_data{}; - void SetUp() override { const size_t type_size = sizeof(int); std::vector data(kDataCount * type_size); @@ -47,15 +49,15 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT } const int root = 0; - input_data = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; + input_data_ = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; } - bool CheckTestOutputData(OutType &output_data) final { - const auto &input = input_data; + bool CheckOutputData(OutType &output_data) { + const auto &input = input_data_; const auto ¶ms = GetParam(); const std::string task_name = std::get<1>(params); - const bool is_mpi = task_name.find("_mpi_") != std::string::npos; + const bool is_mpi = task_name.find("MPI") != std::string::npos; int world_size = 1; int rank = 0; @@ -74,7 +76,6 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT return false; } - // Дополнительная проверка корректности данных для перформанс тестов if (rank == input.root && input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { @@ -91,23 +92,57 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT return true; } - InType GetTestInputData() final { - return input_data; + GatherInput GetInputData() { + return input_data_; + } + + void ExecuteTest() { + const auto ¶ms = GetParam(); + const std::string task_type = std::get<1>(params); + + if (task_type.find("MPI") != std::string::npos) { + LuchnikovETransmFrAllToOneGatherMPI task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } else { + LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } } + + private: + GatherInput input_data_; }; TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { - ExecuteTest(GetParam()); + ExecuteTest(); } -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); +std::vector> CreatePerfTestParams() { + std::vector> params; -const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 0)); -const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; + params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 0)); + + return params; +} -INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, + ::testing::ValuesIn(CreatePerfTestParams()), + [](const testing::TestParamInfo &info) { + return std::get<1>(info.param); + }); } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 4859ef19f25bbf22f5de3c552b23c74592417fac Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 12:41:29 +0300 Subject: [PATCH 14/30] Fix --- .../mpi/src/ops_mpi.cpp | 10 --- .../tests/functional/main.cpp | 78 +++++++++++-------- .../tests/performance/main.cpp | 38 +++++---- 3 files changed, 62 insertions(+), 64 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 4ca563c7..218d0a0e 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -30,14 +28,6 @@ int GetTypeSize(MPI_Datatype datatype) { bool IsPowerOfTwo(int x) { return (x > 0) && ((x & (x - 1)) == 0); } - -int NextPowerOfTwo(int x) { - int power = 1; - while (power < x) { - power <<= 1; - } - return power; -} } // namespace LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 3614fd69..e8e3d1e7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -15,14 +15,12 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { class LuchnikovETransmFrAllToOneGatherFuncTests - : public ::testing::TestWithParam> { + : public ::testing::TestWithParam> { protected: void SetUp() override { - TestType params = std::get<2>(GetParam()); - - const auto &count = std::get<0>(params); - const auto &root = std::get<1>(params); - const auto &datatype = std::get<2>(params); + const auto &count = std::get<2>(GetParam()); + const auto &root = std::get<3>(GetParam()); + const auto &datatype = std::get<4>(GetParam()); int type_size = 0; if (datatype == MPI_INT) { @@ -74,9 +72,8 @@ class LuchnikovETransmFrAllToOneGatherFuncTests bool CheckOutputData(OutType &output_data) { const auto &input = input_data_; - const auto ¶ms = std::get<2>(GetParam()); - const std::string test_name = std::get<1>(GetParam()); - bool is_mpi = test_name.find("MPI") != std::string::npos; + const std::string task_type = std::get<1>(GetParam()); + bool is_mpi = (task_type == "MPI"); int world_size = 1; int rank = 0; @@ -99,6 +96,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests return false; } + // Проверяем корректность собранных данных if (rank == input.root) { if (input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); @@ -117,15 +115,10 @@ class LuchnikovETransmFrAllToOneGatherFuncTests return true; } - GatherInput GetInputData() { - return input_data_; - } - void ExecuteTest() { - const auto ¶ms = GetParam(); - const std::string task_type = std::get<1>(params); + const std::string task_type = std::get<1>(GetParam()); - if (task_type.find("MPI") != std::string::npos) { + if (task_type == "MPI") { LuchnikovETransmFrAllToOneGatherMPI task(input_data_); ASSERT_TRUE(task.Validation()); ASSERT_TRUE(task.PreProcessing()); @@ -156,31 +149,47 @@ TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { ExecuteTest(); } -const std::array kTestParam = {std::make_tuple(1, 0, MPI_INT, "SingleElementIntRoot0"), - std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), - std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), - std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0"), - std::make_tuple(2, 1, MPI_INT, "IntRoot1"), - std::make_tuple(2, 2, MPI_INT, "IntRoot2")}; +// Создаем параметры для тестов +std::vector> CreateTestParams() { + std::vector> params; -std::vector> CreateTestParams() { - std::vector> params; + std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - for (const auto &test_case : kTestParam) { - params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", test_case)); + // Тест 1: count=1, root=0, int + params.push_back(std::make_tuple(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0")); - params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", test_case)); - } + // Тест 2: count=3, root=0, int + params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0")); + + // Тест 3: count=4, root=0, float + params.push_back(std::make_tuple(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); + + // Тест 4: count=3, root=0, double + params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); + + // Тест 5: count=2, root=1, int + params.push_back(std::make_tuple(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1")); + params.push_back(std::make_tuple(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1")); + + // Тест 6: count=2, root=2, int + params.push_back(std::make_tuple(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2")); + params.push_back(std::make_tuple(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2")); return params; } +std::string PrintTestParam(const testing::TestParamInfo &info) { + std::string task_type = std::get<1>(info.param); + std::string test_name = std::get<5>(info.param); + return task_type + "_" + test_name; +} + INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, - ::testing::ValuesIn(CreateTestParams()), - [](const testing::TestParamInfo &info) { - std::string name = std::get<1>(info.param) + "_" + std::get<3>(std::get<2>(info.param)); - return name; - }); + ::testing::ValuesIn(CreateTestParams()), PrintTestParam); TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int rank = 0; @@ -340,9 +349,10 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); + // Проверяем, что размер не является степенью двойки bool is_power_of_two = (world_size > 0) && ((world_size & (world_size - 1)) == 0); - if (!is_power_of_two && world_size > 3) { + if (!is_power_of_two && world_size > 2) { int count = 3; std::vector data(static_cast(count) * sizeof(int)); auto *d_ptr = reinterpret_cast(data.data()); diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 43b2472e..06644648 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -24,10 +24,6 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { } return 0; } - -std::string GetTaskName(const std::tuple ¶m) { - return std::get<1>(param); -} } // namespace class LuchnikovETransmFrAllToOneGatherPerfTests @@ -55,9 +51,8 @@ class LuchnikovETransmFrAllToOneGatherPerfTests bool CheckOutputData(OutType &output_data) { const auto &input = input_data_; - const auto ¶ms = GetParam(); - const std::string task_name = std::get<1>(params); - const bool is_mpi = task_name.find("MPI") != std::string::npos; + const std::string task_type = std::get<1>(GetParam()); + const bool is_mpi = (task_type == "MPI"); int world_size = 1; int rank = 0; @@ -76,6 +71,7 @@ class LuchnikovETransmFrAllToOneGatherPerfTests return false; } + // Проверка корректности данных if (rank == input.root && input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { @@ -92,15 +88,10 @@ class LuchnikovETransmFrAllToOneGatherPerfTests return true; } - GatherInput GetInputData() { - return input_data_; - } - void ExecuteTest() { - const auto ¶ms = GetParam(); - const std::string task_type = std::get<1>(params); + const std::string task_type = std::get<1>(GetParam()); - if (task_type.find("MPI") != std::string::npos) { + if (task_type == "MPI") { LuchnikovETransmFrAllToOneGatherMPI task(input_data_); ASSERT_TRUE(task.Validation()); ASSERT_TRUE(task.PreProcessing()); @@ -129,20 +120,27 @@ TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { ExecuteTest(); } +// Создаем параметры для перформанс тестов std::vector> CreatePerfTestParams() { std::vector> params; - params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 0)); + std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - params.push_back(std::make_tuple("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 0)); + // MPI тест + params.push_back(std::make_tuple(task_name, "MPI", 0)); + + // SEQ тест + params.push_back(std::make_tuple(task_name, "SEQ", 0)); return params; } +std::string PrintPerfTestParam( + const testing::TestParamInfo &info) { + return std::get<1>(info.param); +} + INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, - ::testing::ValuesIn(CreatePerfTestParams()), - [](const testing::TestParamInfo &info) { - return std::get<1>(info.param); - }); + ::testing::ValuesIn(CreatePerfTestParams()), PrintPerfTestParam); } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 84713e21af622fd1355426f138a03df4e09eec58 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 12:49:37 +0300 Subject: [PATCH 15/30] Fix --- .../tests/functional/main.cpp | 81 ++++++++++--------- .../tests/performance/main.cpp | 37 ++++----- 2 files changed, 58 insertions(+), 60 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index e8e3d1e7..11e92f9d 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -14,6 +14,48 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { +namespace { +// Объявляем функции в анонимном пространстве имен +std::vector> CreateTestParams() { + std::vector> params; + + std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; + + // Тест 1: count=1, root=0, int + params.push_back(std::make_tuple(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0")); + + // Тест 2: count=3, root=0, int + params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0")); + + // Тест 3: count=4, root=0, float + params.push_back(std::make_tuple(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); + + // Тест 4: count=3, root=0, double + params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); + params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); + + // Тест 5: count=2, root=1, int + params.push_back(std::make_tuple(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1")); + params.push_back(std::make_tuple(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1")); + + // Тест 6: count=2, root=2, int + params.push_back(std::make_tuple(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2")); + params.push_back(std::make_tuple(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2")); + + return params; +} + +std::string PrintTestParam( + const testing::TestParamInfo> &info) { + std::string task_type = std::get<1>(info.param); + std::string test_name = std::get<5>(info.param); + return task_type + "_" + test_name; +} +} // namespace + class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam> { protected: @@ -149,45 +191,6 @@ TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { ExecuteTest(); } -// Создаем параметры для тестов -std::vector> CreateTestParams() { - std::vector> params; - - std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - - // Тест 1: count=1, root=0, int - params.push_back(std::make_tuple(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0")); - - // Тест 2: count=3, root=0, int - params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0")); - - // Тест 3: count=4, root=0, float - params.push_back(std::make_tuple(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); - - // Тест 4: count=3, root=0, double - params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); - - // Тест 5: count=2, root=1, int - params.push_back(std::make_tuple(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1")); - params.push_back(std::make_tuple(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1")); - - // Тест 6: count=2, root=2, int - params.push_back(std::make_tuple(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2")); - params.push_back(std::make_tuple(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2")); - - return params; -} - -std::string PrintTestParam(const testing::TestParamInfo &info) { - std::string task_type = std::get<1>(info.param); - std::string test_name = std::get<5>(info.param); - return task_type + "_" + test_name; -} - INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, ::testing::ValuesIn(CreateTestParams()), PrintTestParam); diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 06644648..28a1a594 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -24,6 +24,22 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { } return 0; } + +std::vector> CreatePerfTestParams() { + std::vector> params; + + std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; + + params.push_back(std::make_tuple(task_name, "MPI", 0)); + + params.push_back(std::make_tuple(task_name, "SEQ", 0)); + + return params; +} + +std::string PrintPerfTestParam(const testing::TestParamInfo> &info) { + return std::get<1>(info.param); +} } // namespace class LuchnikovETransmFrAllToOneGatherPerfTests @@ -71,7 +87,6 @@ class LuchnikovETransmFrAllToOneGatherPerfTests return false; } - // Проверка корректности данных if (rank == input.root && input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { @@ -120,26 +135,6 @@ TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { ExecuteTest(); } -// Создаем параметры для перформанс тестов -std::vector> CreatePerfTestParams() { - std::vector> params; - - std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - - // MPI тест - params.push_back(std::make_tuple(task_name, "MPI", 0)); - - // SEQ тест - params.push_back(std::make_tuple(task_name, "SEQ", 0)); - - return params; -} - -std::string PrintPerfTestParam( - const testing::TestParamInfo &info) { - return std::get<1>(info.param); -} - INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, ::testing::ValuesIn(CreatePerfTestParams()), PrintPerfTestParam); From c85f73e68b2b9c46854049380091a4d61daf83e0 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 13:17:14 +0300 Subject: [PATCH 16/30] Fix --- .../tests/functional/main.cpp | 79 +++++++++++++++++-- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 11e92f9d..9041a8f3 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -74,7 +75,14 @@ class LuchnikovETransmFrAllToOneGatherFuncTests } size_t total_size = static_cast(count) * static_cast(type_size); - std::vector data(total_size); + // Создаем вектор с помощью reserve и push_back, чтобы избежать potential null pointer dereference + std::vector data; + data.reserve(total_size); + + // Заполняем вектор нулями + for (size_t i = 0; i < total_size; ++i) { + data.push_back(0); + } int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); @@ -151,6 +159,28 @@ class LuchnikovETransmFrAllToOneGatherFuncTests } } } + } else if (input.datatype == MPI_FLOAT) { + const float *out_ptr = reinterpret_cast(output_data.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < input.count; ++j) { + float expected_value = static_cast(i * input.count + j) + 0.5F; + float actual_value = out_ptr[i * input.count + j]; + if (std::abs(actual_value - expected_value) > 1e-6) { + return false; + } + } + } + } else if (input.datatype == MPI_DOUBLE) { + const double *out_ptr = reinterpret_cast(output_data.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < input.count; ++j) { + double expected_value = static_cast(i * input.count + j) + 0.25; + double actual_value = out_ptr[i * input.count + j]; + if (std::abs(actual_value - expected_value) > 1e-12) { + return false; + } + } + } } } @@ -201,7 +231,12 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { MPI_Comm_size(MPI_COMM_WORLD, &world_size); int count = 3; - std::vector data(count * sizeof(int)); + std::vector data; + data.reserve(count * sizeof(int)); + for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { + data.push_back(0); + } + auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { data_ptr[i] = rank * count + i + 1; @@ -231,7 +266,12 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { int count = 3; - std::vector data(count * sizeof(int)); + std::vector data; + data.reserve(count * sizeof(int)); + for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { + data.push_back(0); + } + auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { data_ptr[i] = i + 1; @@ -258,7 +298,11 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { int world_size = 1; MPI_Comm_size(MPI_COMM_WORLD, &world_size); - std::vector data(sizeof(int)); + std::vector data; + data.reserve(sizeof(int)); + for (size_t i = 0; i < sizeof(int); ++i) { + data.push_back(0); + } GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); @@ -272,7 +316,11 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); EXPECT_FALSE(task_3.Validation()); - std::vector wrong_size_data(sizeof(int) * 2); + std::vector wrong_size_data; + wrong_size_data.reserve(sizeof(int) * 2); + for (size_t i = 0; i < sizeof(int) * 2; ++i) { + wrong_size_data.push_back(0); + } GatherInput input_wrong_size{.data = wrong_size_data, .count = 1, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_4(input_wrong_size); EXPECT_FALSE(task_4.Validation()); @@ -286,7 +334,12 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { int root = world_size / 2; int count = 2; - std::vector data(static_cast(count) * sizeof(float)); + std::vector data; + data.reserve(static_cast(count) * sizeof(float)); + for (size_t i = 0; i < static_cast(count) * sizeof(float); ++i) { + data.push_back(0); + } + auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { d_ptr[i] = static_cast(rank * count + i); @@ -319,7 +372,12 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { MPI_Comm_size(MPI_COMM_WORLD, &world_size); int count = 1000; - std::vector data(static_cast(count) * sizeof(double)); + std::vector data; + data.reserve(static_cast(count) * sizeof(double)); + for (size_t i = 0; i < static_cast(count) * sizeof(double); ++i) { + data.push_back(0); + } + auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { d_ptr[i] = static_cast(rank * count + i); @@ -357,7 +415,12 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { if (!is_power_of_two && world_size > 2) { int count = 3; - std::vector data(static_cast(count) * sizeof(int)); + std::vector data; + data.reserve(static_cast(count) * sizeof(int)); + for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { + data.push_back(0); + } + auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { d_ptr[i] = rank * count + i; From a2d8d6633a6ce63fa3fcd5138f6f79bcdd05c2ca Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 14:25:57 +0300 Subject: [PATCH 17/30] Fix --- .../mpi/src/ops_mpi.cpp | 149 +++++++++--------- .../tests/functional/main.cpp | 104 ++++++------ .../tests/performance/main.cpp | 24 +-- 3 files changed, 141 insertions(+), 136 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 218d0a0e..038a13a7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -4,7 +4,8 @@ #include #include -#include +#include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -14,13 +15,13 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { namespace { int GetTypeSize(MPI_Datatype datatype) { if (datatype == MPI_INT) { - return sizeof(int); + return static_cast(sizeof(int)); } if (datatype == MPI_FLOAT) { - return sizeof(float); + return static_cast(sizeof(float)); } if (datatype == MPI_DOUBLE) { - return sizeof(double); + return static_cast(sizeof(double)); } return 0; } @@ -28,6 +29,74 @@ int GetTypeSize(MPI_Datatype datatype) { bool IsPowerOfTwo(int x) { return (x > 0) && ((x & (x - 1)) == 0); } + +void GatherNonPowerOfTwo(int rank, int world_size, const GatherInput &input, int block_size, OutType &output) { + const int root = input.root; + + if (rank == root) { + std::vector recv_buffer(static_cast(world_size) * static_cast(block_size)); + + std::copy(input.data.begin(), input.data.end(), + recv_buffer.begin() + static_cast(rank) * static_cast(block_size)); + + for (int i = 0; i < world_size; ++i) { + if (i != rank) { + MPI_Recv(recv_buffer.data() + static_cast(i) * static_cast(block_size), + block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + } + + output = std::move(recv_buffer); + } else { + MPI_Send(input.data.data(), block_size, MPI_BYTE, root, 0, MPI_COMM_WORLD); + output = std::vector(); + } +} + +void GatherPowerOfTwo(int rank, int world_size, const GatherInput &input, int block_size, OutType &output) { + const int root = input.root; + + std::vector send_buffer(static_cast(block_size)); + std::copy(input.data.begin(), input.data.end(), send_buffer.begin()); + + std::vector recv_buffer; + if (rank == root) { + recv_buffer.resize(static_cast(world_size) * static_cast(block_size)); + std::copy(send_buffer.begin(), send_buffer.end(), recv_buffer.begin()); + } + + int step = 1; + while (step < world_size) { + if (rank % (2 * step) == 0) { + int source = rank + step; + if (source < world_size) { + int recv_size = step * block_size; + std::vector temp_recv(static_cast(recv_size)); + MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + if (rank == root) { + std::copy( + temp_recv.begin(), temp_recv.end(), + recv_buffer.begin() + static_cast(source) * static_cast(block_size)); + } else { + send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); + } + } + } else { + int dest = rank - step; + MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest, 0, MPI_COMM_WORLD); + break; + } + step *= 2; + } + + if (rank == root) { + output = std::move(recv_buffer); + } else { + output = std::vector(); + } +} + } // namespace LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { @@ -81,78 +150,10 @@ bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { const int type_size = GetTypeSize(input.datatype); const int block_size = input.count * type_size; - // Для нестепени двойки используем простой алгоритм с прямыми передачами if (!IsPowerOfTwo(world_size)) { - if (rank == input.root) { - // Корневой процесс собирает данные от всех - std::vector recv_buffer(static_cast(world_size) * static_cast(block_size)); - - // Копируем свои данные - std::copy(input.data.begin(), input.data.end(), - recv_buffer.begin() + static_cast(rank * block_size)); - - // Получаем данные от всех остальных процессов - for (int i = 0; i < world_size; ++i) { - if (i != rank) { - MPI_Recv(recv_buffer.data() + i * block_size, block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - } - } - - GetOutput() = std::move(recv_buffer); - } else { - // Некорневые процессы отправляют свои данные корню - MPI_Send(input.data.data(), block_size, MPI_BYTE, input.root, 0, MPI_COMM_WORLD); - GetOutput() = std::vector(); - } - - return true; - } - - // Для степени двойки используем древовидный алгоритм - std::vector send_buffer(block_size); - std::copy(input.data.begin(), input.data.end(), send_buffer.begin()); - - std::vector recv_buffer; - if (rank == input.root) { - recv_buffer.resize(static_cast(world_size) * static_cast(block_size)); - // Копируем свои данные в начало буфера - std::copy(send_buffer.begin(), send_buffer.end(), recv_buffer.begin()); - } - - // Древовидный сбор данных - int step = 1; - while (step < world_size) { - if (rank % (2 * step) == 0) { - // Принимаем данные от процессов с шагом step - int source = rank + step; - if (source < world_size) { - int recv_size = step * block_size; - std::vector temp_recv(recv_size); - MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - - // Вставляем полученные данные в правильную позицию - if (rank == input.root) { - // Корень сразу сохраняет в финальный буфер - std::copy(temp_recv.begin(), temp_recv.end(), - recv_buffer.begin() + static_cast(source * block_size)); - } else { - // Промежуточные узлы накапливают данные для отправки выше - send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); - } - } - } else { - // Отправляем данные родительскому процессу - int dest = rank - step; - MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest, 0, MPI_COMM_WORLD); - break; - } - step *= 2; - } - - if (rank == input.root) { - GetOutput() = std::move(recv_buffer); + GatherNonPowerOfTwo(rank, world_size, input, block_size, GetOutput()); } else { - GetOutput() = std::vector(); + GatherPowerOfTwo(rank, world_size, input, block_size, GetOutput()); } return true; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 9041a8f3..ddd9990b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,10 +1,9 @@ #include #include -#include -#include +#include #include -#include +#include #include #include #include @@ -16,49 +15,48 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { namespace { -// Объявляем функции в анонимном пространстве имен -std::vector> CreateTestParams() { - std::vector> params; +using TestParam = std::tuple; + +std::vector CreateTestParams() { + std::vector params; std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; // Тест 1: count=1, root=0, int - params.push_back(std::make_tuple(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0")); + params.emplace_back(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0"); + params.emplace_back(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0"); // Тест 2: count=3, root=0, int - params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0")); + params.emplace_back(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0"); + params.emplace_back(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0"); // Тест 3: count=4, root=0, float - params.push_back(std::make_tuple(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0")); + params.emplace_back(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); + params.emplace_back(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); // Тест 4: count=3, root=0, double - params.push_back(std::make_tuple(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); - params.push_back(std::make_tuple(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0")); + params.emplace_back(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); + params.emplace_back(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); // Тест 5: count=2, root=1, int - params.push_back(std::make_tuple(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1")); - params.push_back(std::make_tuple(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1")); + params.emplace_back(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1"); + params.emplace_back(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1"); // Тест 6: count=2, root=2, int - params.push_back(std::make_tuple(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2")); - params.push_back(std::make_tuple(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2")); + params.emplace_back(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2"); + params.emplace_back(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2"); return params; } -std::string PrintTestParam( - const testing::TestParamInfo> &info) { +std::string PrintTestParam(const testing::TestParamInfo &info) { std::string task_type = std::get<1>(info.param); std::string test_name = std::get<5>(info.param); return task_type + "_" + test_name; } } // namespace -class LuchnikovETransmFrAllToOneGatherFuncTests - : public ::testing::TestWithParam> { +class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam { protected: void SetUp() override { const auto &count = std::get<2>(GetParam()); @@ -67,15 +65,15 @@ class LuchnikovETransmFrAllToOneGatherFuncTests int type_size = 0; if (datatype == MPI_INT) { - type_size = sizeof(int); + type_size = static_cast(sizeof(int)); } else if (datatype == MPI_FLOAT) { - type_size = sizeof(float); + type_size = static_cast(sizeof(float)); } else if (datatype == MPI_DOUBLE) { - type_size = sizeof(double); + type_size = static_cast(sizeof(double)); } size_t total_size = static_cast(count) * static_cast(type_size); - // Создаем вектор с помощью reserve и push_back, чтобы избежать potential null pointer dereference + // Создаем вектор с помощью reserve и push_back std::vector data; data.reserve(total_size); @@ -90,17 +88,17 @@ class LuchnikovETransmFrAllToOneGatherFuncTests if (datatype == MPI_INT) { auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = rank * count + i + 1; + data_ptr[i] = (rank * count) + i + 1; } } else if (datatype == MPI_FLOAT) { auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = static_cast(rank * count + i) + 0.5F; + data_ptr[i] = static_cast((rank * count) + i) + 0.5F; } } else if (datatype == MPI_DOUBLE) { auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = static_cast(rank * count + i) + 0.25; + data_ptr[i] = static_cast((rank * count) + i) + 0.25; } } @@ -109,13 +107,13 @@ class LuchnikovETransmFrAllToOneGatherFuncTests static int GetTypeSize(MPI_Datatype datatype) { if (datatype == MPI_INT) { - return sizeof(int); + return static_cast(sizeof(int)); } if (datatype == MPI_FLOAT) { - return sizeof(float); + return static_cast(sizeof(float)); } if (datatype == MPI_DOUBLE) { - return sizeof(double); + return static_cast(sizeof(double)); } return 0; } @@ -123,7 +121,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests bool CheckOutputData(OutType &output_data) { const auto &input = input_data_; const std::string task_type = std::get<1>(GetParam()); - bool is_mpi = (task_type == "MPI"); + const bool is_mpi = (task_type == "MPI"); int world_size = 1; int rank = 0; @@ -149,33 +147,33 @@ class LuchnikovETransmFrAllToOneGatherFuncTests // Проверяем корректность собранных данных if (rank == input.root) { if (input.datatype == MPI_INT) { - const int *out_ptr = reinterpret_cast(output_data.data()); + const auto *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < input.count; ++j) { - int expected_value = i * input.count + j + 1; - int actual_value = out_ptr[i * input.count + j]; + int expected_value = (i * input.count) + j + 1; + int actual_value = out_ptr[(i * input.count) + j]; if (actual_value != expected_value) { return false; } } } } else if (input.datatype == MPI_FLOAT) { - const float *out_ptr = reinterpret_cast(output_data.data()); + const auto *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < input.count; ++j) { - float expected_value = static_cast(i * input.count + j) + 0.5F; - float actual_value = out_ptr[i * input.count + j]; - if (std::abs(actual_value - expected_value) > 1e-6) { + float expected_value = static_cast((i * input.count) + j) + 0.5F; + float actual_value = out_ptr[(i * input.count) + j]; + if (std::abs(actual_value - expected_value) > 1e-6F) { return false; } } } } else if (input.datatype == MPI_DOUBLE) { - const double *out_ptr = reinterpret_cast(output_data.data()); + const auto *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < input.count; ++j) { - double expected_value = static_cast(i * input.count + j) + 0.25; - double actual_value = out_ptr[i * input.count + j]; + double expected_value = static_cast((i * input.count) + j) + 0.25; + double actual_value = out_ptr[(i * input.count) + j]; if (std::abs(actual_value - expected_value) > 1e-12) { return false; } @@ -232,14 +230,14 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int count = 3; std::vector data; - data.reserve(count * sizeof(int)); + data.reserve(static_cast(count) * sizeof(int)); for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { data.push_back(0); } auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = rank * count + i + 1; + data_ptr[i] = (rank * count) + i + 1; } GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; @@ -258,7 +256,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { const int *res_ptr = reinterpret_cast(result.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[i * count + j], i * count + j + 1); + EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j + 1); } } } @@ -267,7 +265,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { int count = 3; std::vector data; - data.reserve(count * sizeof(int)); + data.reserve(static_cast(count) * sizeof(int)); for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { data.push_back(0); } @@ -342,7 +340,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - d_ptr[i] = static_cast(rank * count + i); + d_ptr[i] = static_cast((rank * count) + i); } GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; @@ -359,7 +357,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { const auto *res_ptr = reinterpret_cast(result.data()); for (int rank_id = 0; rank_id < world_size; ++rank_id) { for (int i = 0; i < count; ++i) { - EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast(rank_id * count + i)); + EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast((rank_id * count) + i)); } } } @@ -380,7 +378,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - d_ptr[i] = static_cast(rank * count + i); + d_ptr[i] = static_cast((rank * count) + i); } GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; @@ -398,7 +396,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { const double *res_ptr = reinterpret_cast(result.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - EXPECT_DOUBLE_EQ(res_ptr[i * count + j], static_cast(i * count + j)); + EXPECT_DOUBLE_EQ(res_ptr[(i * count) + j], static_cast((i * count) + j)); } } } @@ -423,7 +421,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - d_ptr[i] = rank * count + i; + d_ptr[i] = (rank * count) + i; } GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; @@ -441,7 +439,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { const int *res_ptr = reinterpret_cast(result.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[i * count + j], i * count + j); + EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j); } } } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 28a1a594..51b45ae0 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -1,8 +1,10 @@ #include #include +#include #include #include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" @@ -25,25 +27,28 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { return 0; } -std::vector> CreatePerfTestParams() { - std::vector> params; +using PerfTestParam = std::tuple; + +std::vector CreatePerfTestParams() { + std::vector params; std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - params.push_back(std::make_tuple(task_name, "MPI", 0)); + // MPI тест + params.emplace_back(task_name, "MPI", 0); - params.push_back(std::make_tuple(task_name, "SEQ", 0)); + // SEQ тест + params.emplace_back(task_name, "SEQ", 0); return params; } -std::string PrintPerfTestParam(const testing::TestParamInfo> &info) { +std::string PrintPerfTestParam(const testing::TestParamInfo &info) { return std::get<1>(info.param); } } // namespace -class LuchnikovETransmFrAllToOneGatherPerfTests - : public ::testing::TestWithParam> { +class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithParam { protected: static const size_t kDataCount = 100000; MPI_Datatype data_type = MPI_INT; @@ -87,12 +92,13 @@ class LuchnikovETransmFrAllToOneGatherPerfTests return false; } + // Проверка корректности данных if (rank == input.root && input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { for (size_t j = 0; j < kDataCount; ++j) { - int expected = static_cast(i * static_cast(kDataCount) + static_cast(j)); - int actual = out_ptr[i * static_cast(kDataCount) + static_cast(j)]; + int expected = static_cast((i * static_cast(kDataCount)) + static_cast(j)); + int actual = out_ptr[(i * static_cast(kDataCount)) + static_cast(j)]; if (actual != expected) { return false; } From 71836471f0e35a4b006d9dc2b833d858b9381c87 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 17:25:13 +0300 Subject: [PATCH 18/30] fixTidy --- .../mpi/src/ops_mpi.cpp | 16 +- .../seq/src/ops_seq.cpp | 2 - .../tests/functional/main.cpp | 357 ++++++++---------- .../tests/performance/main.cpp | 24 +- 4 files changed, 182 insertions(+), 217 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 038a13a7..00f98950 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -36,12 +35,12 @@ void GatherNonPowerOfTwo(int rank, int world_size, const GatherInput &input, int if (rank == root) { std::vector recv_buffer(static_cast(world_size) * static_cast(block_size)); - std::copy(input.data.begin(), input.data.end(), - recv_buffer.begin() + static_cast(rank) * static_cast(block_size)); + std::ranges::copy( + input.data, recv_buffer.begin() + static_cast(rank) * static_cast(block_size)); for (int i = 0; i < world_size; ++i) { if (i != rank) { - MPI_Recv(recv_buffer.data() + static_cast(i) * static_cast(block_size), + MPI_Recv(recv_buffer.data() + (static_cast(i) * static_cast(block_size)), block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } @@ -57,12 +56,12 @@ void GatherPowerOfTwo(int rank, int world_size, const GatherInput &input, int bl const int root = input.root; std::vector send_buffer(static_cast(block_size)); - std::copy(input.data.begin(), input.data.end(), send_buffer.begin()); + std::ranges::copy(input.data, send_buffer.begin()); std::vector recv_buffer; if (rank == root) { recv_buffer.resize(static_cast(world_size) * static_cast(block_size)); - std::copy(send_buffer.begin(), send_buffer.end(), recv_buffer.begin()); + std::ranges::copy(send_buffer, recv_buffer.begin()); } int step = 1; @@ -75,9 +74,8 @@ void GatherPowerOfTwo(int rank, int world_size, const GatherInput &input, int bl MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); if (rank == root) { - std::copy( - temp_recv.begin(), temp_recv.end(), - recv_buffer.begin() + static_cast(source) * static_cast(block_size)); + std::ranges::copy(temp_recv, recv_buffer.begin() + (static_cast(source) * + static_cast(block_size))); } else { send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index 33aefcf1..d85b8d24 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -59,9 +59,7 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::PreProcessingImpl() { bool LuchnikovETransmFrAllToOneGatherSEQ::RunImpl() { const auto &input = GetInput(); - GetOutput() = input.data; - return true; } diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index ddd9990b..88455b6b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -3,10 +3,8 @@ #include #include -#include #include #include -#include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" @@ -20,45 +18,33 @@ using TestParam = std::tuple CreateTestParams() { std::vector params; - std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - - // Тест 1: count=1, root=0, int - params.emplace_back(task_name, "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0"); - params.emplace_back(task_name, "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0"); - - // Тест 2: count=3, root=0, int - params.emplace_back(task_name, "MPI", 3, 0, MPI_INT, "SmallIntRoot0"); - params.emplace_back(task_name, "SEQ", 3, 0, MPI_INT, "SmallIntRoot0"); - - // Тест 3: count=4, root=0, float - params.emplace_back(task_name, "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); - params.emplace_back(task_name, "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); - - // Тест 4: count=3, root=0, double - params.emplace_back(task_name, "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); - params.emplace_back(task_name, "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); - - // Тест 5: count=2, root=1, int - params.emplace_back(task_name, "MPI", 2, 1, MPI_INT, "IntRoot1"); - params.emplace_back(task_name, "SEQ", 2, 1, MPI_INT, "IntRoot1"); - - // Тест 6: count=2, root=2, int - params.emplace_back(task_name, "MPI", 2, 2, MPI_INT, "IntRoot2"); - params.emplace_back(task_name, "SEQ", 2, 2, MPI_INT, "IntRoot2"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 3, 0, MPI_INT, "SmallIntRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 3, 0, MPI_INT, "SmallIntRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 2, 1, MPI_INT, "IntRoot1"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 2, 1, MPI_INT, "IntRoot1"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 2, 2, MPI_INT, "IntRoot2"); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 2, 2, MPI_INT, "IntRoot2"); return params; } std::string PrintTestParam(const testing::TestParamInfo &info) { - std::string task_type = std::get<1>(info.param); - std::string test_name = std::get<5>(info.param); - return task_type + "_" + test_name; + return std::get<1>(info.param) + "_" + std::get<5>(info.param); } } // namespace class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam { + public: + LuchnikovETransmFrAllToOneGatherFuncTests() = default; + protected: - void SetUp() override { + void static SetUp() override { const auto &count = std::get<2>(GetParam()); const auto &root = std::get<3>(GetParam()); const auto &datatype = std::get<4>(GetParam()); @@ -72,15 +58,8 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara type_size = static_cast(sizeof(double)); } - size_t total_size = static_cast(count) * static_cast(type_size); - // Создаем вектор с помощью reserve и push_back - std::vector data; - data.reserve(total_size); - - // Заполняем вектор нулями - for (size_t i = 0; i < total_size; ++i) { - data.push_back(0); - } + const size_t total_size = static_cast(count) * static_cast(type_size); + std::vector data(total_size, 0); int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); @@ -118,99 +97,112 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara return 0; } - bool CheckOutputData(OutType &output_data) { - const auto &input = input_data_; + bool static CheckIntOutput(const int *data, int world_size, int count) const { + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + if (data[(i * count) + j] != (i * count) + j + 1) { + return false; + } + } + } + return true; + } + + bool static CheckFloatOutput(const float *data, int world_size, int count) const { + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + if (std::abs(data[(i * count) + j] - (static_cast((i * count) + j) + 0.5F)) > 1e-6F) { + return false; + } + } + } + return true; + } + + bool static CheckDoubleOutput(const double *data, int world_size, int count) const { + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + if (std::abs(data[(i * count) + j] - (static_cast((i * count) + j) + 0.25)) > 1e-12) { + return false; + } + } + } + return true; + } + + bool static ValidateOutputSize(const OutType &output, int world_size) const { + if (output.empty()) { + return false; + } + const size_t expected = 0; + expected = static_cast(input_data_.count) * static_cast(world_size) * + static_cast(GetTypeSize(input_data_.datatype)); + return output.size() == expected; + } + + bool static CheckOutputData(OutType &output_data) { const std::string task_type = std::get<1>(GetParam()); const bool is_mpi = (task_type == "MPI"); int world_size = 1; int rank = 0; + if (is_mpi) { MPI_Comm_size(MPI_COMM_WORLD, &world_size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != input.root) { + if (rank != input_data_.root) { return true; } } - if (output_data.empty()) { + if (!ValidateOutputSize(output_data, world_size)) { return false; } - const auto type_size = static_cast(GetTypeSize(input.datatype)); - const size_t expected_size = static_cast(input.count) * static_cast(world_size) * type_size; - - if (output_data.size() != expected_size) { - return false; + if (input_data_.datatype == MPI_INT) { + return CheckIntOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); } - - // Проверяем корректность собранных данных - if (rank == input.root) { - if (input.datatype == MPI_INT) { - const auto *out_ptr = reinterpret_cast(output_data.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < input.count; ++j) { - int expected_value = (i * input.count) + j + 1; - int actual_value = out_ptr[(i * input.count) + j]; - if (actual_value != expected_value) { - return false; - } - } - } - } else if (input.datatype == MPI_FLOAT) { - const auto *out_ptr = reinterpret_cast(output_data.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < input.count; ++j) { - float expected_value = static_cast((i * input.count) + j) + 0.5F; - float actual_value = out_ptr[(i * input.count) + j]; - if (std::abs(actual_value - expected_value) > 1e-6F) { - return false; - } - } - } - } else if (input.datatype == MPI_DOUBLE) { - const auto *out_ptr = reinterpret_cast(output_data.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < input.count; ++j) { - double expected_value = static_cast((i * input.count) + j) + 0.25; - double actual_value = out_ptr[(i * input.count) + j]; - if (std::abs(actual_value - expected_value) > 1e-12) { - return false; - } - } - } - } + if (input_data_.datatype == MPI_FLOAT) { + return CheckFloatOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); + } + if (input_data_.datatype == MPI_DOUBLE) { + return CheckDoubleOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); } - return true; + return false; } - void ExecuteTest() { - const std::string task_type = std::get<1>(GetParam()); + void static ExecuteMPITask() { + LuchnikovETransmFrAllToOneGatherMPI task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } + + void static ExecuteSEQTask() { + LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); + } + void static ExecuteTest() { + const std::string task_type = std::get<1>(GetParam()); if (task_type == "MPI") { - LuchnikovETransmFrAllToOneGatherMPI task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); + ExecuteMPITask(); } else { - LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); + ExecuteSEQTask(); } } private: - GatherInput input_data_; + GatherInput input_data_{}; }; namespace { @@ -222,18 +214,26 @@ TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, ::testing::ValuesIn(CreateTestParams()), PrintTestParam); +void ValidateMPIGatherResult(const OutType &result, int count, int world_size) { + EXPECT_FALSE(result.empty()); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); + + const int *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j + 1); + } + } +} + TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int rank = 0; int world_size = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); - int count = 3; - std::vector data; - data.reserve(static_cast(count) * sizeof(int)); - for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { - data.push_back(0); - } + const int count = 3; + std::vector data(static_cast(count) * sizeof(int), 0); auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { @@ -249,26 +249,13 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { EXPECT_TRUE(task.PostProcessing()); if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_FALSE(result.empty()); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); - - const int *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j + 1); - } - } + ValidateMPIGatherResult(task.GetOutput(), count, world_size); } } TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { - int count = 3; - std::vector data; - data.reserve(static_cast(count) * sizeof(int)); - for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { - data.push_back(0); - } + const int count = 3; + std::vector data(static_cast(count) * sizeof(int), 0); auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { @@ -296,11 +283,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { int world_size = 1; MPI_Comm_size(MPI_COMM_WORLD, &world_size); - std::vector data; - data.reserve(sizeof(int)); - for (size_t i = 0; i < sizeof(int); ++i) { - data.push_back(0); - } + std::vector data(sizeof(int), 0); GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); @@ -314,29 +297,36 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); EXPECT_FALSE(task_3.Validation()); - std::vector wrong_size_data; - wrong_size_data.reserve(sizeof(int) * 2); - for (size_t i = 0; i < sizeof(int) * 2; ++i) { - wrong_size_data.push_back(0); - } + std::vector wrong_size_data(sizeof(int) * 2, 0); GatherInput input_wrong_size{.data = wrong_size_data, .count = 1, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_4(input_wrong_size); EXPECT_FALSE(task_4.Validation()); } +void ValidateFloatGatherResult(const OutType &result, int count, int world_size, int root, int rank) { + if (rank != root) { + return; + } + + ASSERT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(float)); + const auto *res_ptr = reinterpret_cast(result.data()); + + for (int rank_id = 0; rank_id < world_size; ++rank_id) { + for (int i = 0; i < count; ++i) { + EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast((rank_id * count) + i)); + } + } +} + TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { int rank = 0; int world_size = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); - int root = world_size / 2; - int count = 2; - std::vector data; - data.reserve(static_cast(count) * sizeof(float)); - for (size_t i = 0; i < static_cast(count) * sizeof(float); ++i) { - data.push_back(0); - } + const int root = world_size / 2; + const int count = 2; + std::vector data(static_cast(count) * sizeof(float), 0); auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { @@ -351,16 +341,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { task.Run(); task.PostProcessing(); - if (rank == root) { - const auto &result = task.GetOutput(); - ASSERT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(float)); - const auto *res_ptr = reinterpret_cast(result.data()); - for (int rank_id = 0; rank_id < world_size; ++rank_id) { - for (int i = 0; i < count; ++i) { - EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast((rank_id * count) + i)); - } - } - } + ValidateFloatGatherResult(task.GetOutput(), count, world_size, root, rank); } TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { @@ -369,12 +350,8 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); - int count = 1000; - std::vector data; - data.reserve(static_cast(count) * sizeof(double)); - for (size_t i = 0; i < static_cast(count) * sizeof(double); ++i) { - data.push_back(0); - } + const int count = 1000; + std::vector data(static_cast(count) * sizeof(double), 0); auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { @@ -393,7 +370,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { const auto &result = task.GetOutput(); EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(double)); - const double *res_ptr = reinterpret_cast(result.data()); + const auto *res_ptr = reinterpret_cast(result.data()); for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { EXPECT_DOUBLE_EQ(res_ptr[(i * count) + j], static_cast((i * count) + j)); @@ -408,44 +385,40 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); - // Проверяем, что размер не является степенью двойки - bool is_power_of_two = (world_size > 0) && ((world_size & (world_size - 1)) == 0); + const bool is_power_of_two = (world_size > 0) && ((world_size & (world_size - 1)) == 0); - if (!is_power_of_two && world_size > 2) { - int count = 3; - std::vector data; - data.reserve(static_cast(count) * sizeof(int)); - for (size_t i = 0; i < static_cast(count) * sizeof(int); ++i) { - data.push_back(0); - } + if (is_power_of_two || world_size <= 2) { + return; + } - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - d_ptr[i] = (rank * count) + i; - } + const int count = 3; + std::vector data(static_cast(count) * sizeof(int), 0); - GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); + auto *d_ptr = reinterpret_cast(data.data()); + for (int i = 0; i < count; ++i) { + d_ptr[i] = (rank * count) + i; + } - ASSERT_TRUE(task.Validation()); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); - - if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); - - const int *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j); - } + GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + ASSERT_TRUE(task.Validation()); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); + + const int *res_ptr = reinterpret_cast(result.data()); + for (int i = 0; i < world_size; ++i) { + for (int j = 0; j < count; ++j) { + EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j); } } } } } // namespace - } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 51b45ae0..ddb96343 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -32,13 +32,8 @@ using PerfTestParam = std::tuple; std::vector CreatePerfTestParams() { std::vector params; - std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - - // MPI тест - params.emplace_back(task_name, "MPI", 0); - - // SEQ тест - params.emplace_back(task_name, "SEQ", 0); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 0); + params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 0); return params; } @@ -52,8 +47,9 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara protected: static const size_t kDataCount = 100000; MPI_Datatype data_type = MPI_INT; + LuchnikovETransmFrAllToOneGatherPerfTests() : input_data_() = default; - void SetUp() override { + void static SetUp() override { const size_t type_size = sizeof(int); std::vector data(kDataCount * type_size); @@ -69,7 +65,7 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara input_data_ = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; } - bool CheckOutputData(OutType &output_data) { + bool static CheckOutputData(OutType &output_data) { const auto &input = input_data_; const std::string task_type = std::get<1>(GetParam()); @@ -84,7 +80,7 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara return true; } } - + const size_t type_size = 0; const size_t type_size = GetTypeSizeSeq(input.datatype); const size_t expected_size = static_cast(input.count) * static_cast(world_size) * type_size; @@ -92,12 +88,11 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara return false; } - // Проверка корректности данных if (rank == input.root && input.datatype == MPI_INT) { const int *out_ptr = reinterpret_cast(output_data.data()); for (int i = 0; i < world_size; ++i) { for (size_t j = 0; j < kDataCount; ++j) { - int expected = static_cast((i * static_cast(kDataCount)) + static_cast(j)); + int expected = (i * static_cast(kDataCount)) + static_cast(j); int actual = out_ptr[(i * static_cast(kDataCount)) + static_cast(j)]; if (actual != expected) { return false; @@ -109,7 +104,7 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara return true; } - void ExecuteTest() { + void static ExecuteTest() { const std::string task_type = std::get<1>(GetParam()); if (task_type == "MPI") { @@ -136,10 +131,11 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithPara private: GatherInput input_data_; }; - +namespace { TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { ExecuteTest(); } +} // namespace INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, ::testing::ValuesIn(CreatePerfTestParams()), PrintPerfTestParam); From 4906336a85f254c33dcf6d619d30791c30920af4 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 18:01:18 +0300 Subject: [PATCH 19/30] fixTidy --- .../tests/functional/main.cpp | 445 ++++++------------ 1 file changed, 134 insertions(+), 311 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 88455b6b..4329ce95 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" @@ -13,94 +14,112 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { namespace { -using TestParam = std::tuple; - -std::vector CreateTestParams() { - std::vector params; - - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 1, 0, MPI_INT, "SingleElementIntRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 1, 0, MPI_INT, "SingleElementIntRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 3, 0, MPI_INT, "SmallIntRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 3, 0, MPI_INT, "SmallIntRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 4, 0, MPI_FLOAT, "SmallFloatRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 3, 0, MPI_DOUBLE, "SmallDoubleRoot0"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 2, 1, MPI_INT, "IntRoot1"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 2, 1, MPI_INT, "IntRoot1"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 2, 2, MPI_INT, "IntRoot2"); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 2, 2, MPI_INT, "IntRoot2"); +using FuncTestParam = std::tuple; + +std::vector CreateFuncTestParams() { + std::vector params; + std::string task_name; + + std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; + + std::vector data_types = {MPI_INT, MPI_FLOAT, MPI_DOUBLE}; + std::vector counts = {1, 10, 100, 1000}; + + for (const auto &datatype : data_types) { + for (const auto &count : counts) { + params.emplace_back(task_name, "MPI", datatype, count); + params.emplace_back(task_name, "SEQ", datatype, count); + } + } return params; } -std::string PrintTestParam(const testing::TestParamInfo &info) { - return std::get<1>(info.param) + "_" + std::get<5>(info.param); +std::string PrintFuncTestParam(const testing::TestParamInfo &info) { + std::string task_type; + std::string task_type = std::get<1>(info.param); + std::string data_type_str; + + MPI_Datatype datatype = std::get<2>(info.param); + if (datatype == MPI_INT) { + data_type_str = "Int" + }; else if (datatype == MPI_FLOAT) { + data_type_str = "Float" + }; else if (datatype == MPI_DOUBLE) { + data_type_str = "Double" + }; + + int count = std::get<3>(info.param); + + return task_type + "_" + data_type_str + "_" + std::to_string(count); } } // namespace -class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam { - public: - LuchnikovETransmFrAllToOneGatherFuncTests() = default; - +class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam { protected: - void static SetUp() override { - const auto &count = std::get<2>(GetParam()); - const auto &root = std::get<3>(GetParam()); - const auto &datatype = std::get<4>(GetParam()); + std::string task_name; + std::string task_type; + MPI_Datatype datatype = MPI_DATATYPE_NULL; + int count = 0; + int root = 0; + GatherInput input_data{nullptr, 0, MPI_DATATYPE_NULL, 0}; + + void SetUp() override { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); - int type_size = 0; - if (datatype == MPI_INT) { - type_size = static_cast(sizeof(int)); - } else if (datatype == MPI_FLOAT) { - type_size = static_cast(sizeof(float)); - } else if (datatype == MPI_DOUBLE) { - type_size = static_cast(sizeof(double)); - } + std::tie(task_name, task_type, datatype, count) = GetParam(); - const size_t total_size = static_cast(count) * static_cast(type_size); - std::vector data(total_size, 0); + input_data_ = GatherInput{ + .data = GenerateData(count_, datatype_, rank), .count = count_, .datatype = datatype_, .root = root_}; + } - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + std::vector static GenerateData(int count, MPI_Datatype datatype, int rank) { + size_t type_size = 0; + size_t type_size = GetTypeSize(datatype); + std::vector data(count * type_size); if (datatype == MPI_INT) { - auto *data_ptr = reinterpret_cast(data.data()); + int *ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = (rank * count) + i + 1; + ptr[i] = (rank * count) + i; } } else if (datatype == MPI_FLOAT) { - auto *data_ptr = reinterpret_cast(data.data()); + auto *ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = static_cast((rank * count) + i) + 0.5F; + ptr[i] = static_cast((rank * count) + i); } } else if (datatype == MPI_DOUBLE) { - auto *data_ptr = reinterpret_cast(data.data()); + auto *ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; ++i) { - data_ptr[i] = static_cast((rank * count) + i) + 0.25; + ptr[i] = static_cast((rank * count) + i); } } - input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; + return data; } - static int GetTypeSize(MPI_Datatype datatype) { + size_t static GetTypeSize(MPI_Datatype datatype) const { if (datatype == MPI_INT) { - return static_cast(sizeof(int)); - } + return sizeof(int) + }; if (datatype == MPI_FLOAT) { - return static_cast(sizeof(float)); - } + return sizeof(float) + }; if (datatype == MPI_DOUBLE) { - return static_cast(sizeof(double)); - } + return sizeof(double) + }; return 0; } bool static CheckIntOutput(const int *data, int world_size, int count) const { for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - if (data[(i * count) + j] != (i * count) + j + 1) { + int expected = (i * count) + j; + int actual = data[(i * count) + j]; + if (actual != expected) { + std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual + << std::endl; return false; } } @@ -108,10 +127,15 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara return true; } - bool static CheckFloatOutput(const float *data, int world_size, int count) const { + bool static CheckFloatOutput(const float *data, int world_size, int count) { + const float epsilon = 1e-6F; for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - if (std::abs(data[(i * count) + j] - (static_cast((i * count) + j) + 0.5F)) > 1e-6F) { + auto expected = static_cast((i * count) + j); + float actual = data[(i * count) + j]; + if (std::abs(actual - expected) > epsilon) { + std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual + << std::endl; return false; } } @@ -119,10 +143,15 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara return true; } - bool static CheckDoubleOutput(const double *data, int world_size, int count) const { + bool static CheckDoubleOutput(const double *data, int world_size, int count) { + const double epsilon = 1e-12; for (int i = 0; i < world_size; ++i) { for (int j = 0; j < count; ++j) { - if (std::abs(data[(i * count) + j] - (static_cast((i * count) + j) + 0.25)) > 1e-12) { + auto expected = static_cast((i * count) + j); + double actual = data[(i * count) + j]; + if (std::abs(actual - expected) > epsilon) { + std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual + << std::endl; return false; } } @@ -130,29 +159,24 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara return true; } - bool static ValidateOutputSize(const OutType &output, int world_size) const { - if (output.empty()) { - return false; - } - const size_t expected = 0; - expected = static_cast(input_data_.count) * static_cast(world_size) * - static_cast(GetTypeSize(input_data_.datatype)); - return output.size() == expected; + bool static ValidateOutputSize(const OutType &output, int world_size) { + size_t expected_size = 0; + size_t expected_size = + static_cast(input_data_.count) * static_cast(world_size) * GetTypeSize(input_data_.datatype); + + bool sizes_match = (output.size() == expected_size); + return sizes_match; } bool static CheckOutputData(OutType &output_data) { - const std::string task_type = std::get<1>(GetParam()); - const bool is_mpi = (task_type == "MPI"); - int world_size = 1; int rank = 0; - if (is_mpi) { - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != input_data_.root) { - return true; - } + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank != input_data_.root) { + return true; } if (!ValidateOutputSize(output_data, world_size)) { @@ -172,253 +196,52 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithPara return false; } - void static ExecuteMPITask() { - LuchnikovETransmFrAllToOneGatherMPI task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); - } - - void static ExecuteSEQTask() { - LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); - } - - void static ExecuteTest() { - const std::string task_type = std::get<1>(GetParam()); - if (task_type == "MPI") { - ExecuteMPITask(); - } else { - ExecuteSEQTask(); - } - } - - private: - GatherInput input_data_{}; -}; - -namespace { - -TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { - ExecuteTest(); -} - -INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, - ::testing::ValuesIn(CreateTestParams()), PrintTestParam); - -void ValidateMPIGatherResult(const OutType &result, int count, int world_size) { - EXPECT_FALSE(result.empty()); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); - - const int *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j + 1); - } - } -} - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { - int rank = 0; - int world_size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - - const int count = 3; - std::vector data(static_cast(count) * sizeof(int), 0); - - auto *data_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - data_ptr[i] = (rank * count) + i + 1; - } - - GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - - EXPECT_TRUE(task.Validation()); - EXPECT_TRUE(task.PreProcessing()); - EXPECT_TRUE(task.Run()); - EXPECT_TRUE(task.PostProcessing()); - - if (rank == 0) { - ValidateMPIGatherResult(task.GetOutput(), count, world_size); - } -} - -TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { - const int count = 3; - std::vector data(static_cast(count) * sizeof(int), 0); - - auto *data_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - data_ptr[i] = i + 1; - } - - GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherSEQ task(input); - - EXPECT_TRUE(task.Validation()); - EXPECT_TRUE(task.PreProcessing()); - EXPECT_TRUE(task.Run()); - EXPECT_TRUE(task.PostProcessing()); - - const auto &result = task.GetOutput(); - ASSERT_EQ(result.size(), static_cast(count) * sizeof(int)); - - const int *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < count; ++i) { - EXPECT_EQ(res_ptr[i], i + 1); - } -} - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { - int world_size = 1; - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - - std::vector data(sizeof(int), 0); - - GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); - EXPECT_FALSE(task_1.Validation()); - - GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = world_size}; - LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); - EXPECT_FALSE(task_2.Validation()); - - GatherInput input_wrong_type{.data = data, .count = 1, .datatype = MPI_CHAR, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); - EXPECT_FALSE(task_3.Validation()); - - std::vector wrong_size_data(sizeof(int) * 2, 0); - GatherInput input_wrong_size{.data = wrong_size_data, .count = 1, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task_4(input_wrong_size); - EXPECT_FALSE(task_4.Validation()); -} - -void ValidateFloatGatherResult(const OutType &result, int count, int world_size, int root, int rank) { - if (rank != root) { - return; - } - - ASSERT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(float)); - const auto *res_ptr = reinterpret_cast(result.data()); - - for (int rank_id = 0; rank_id < world_size; ++rank_id) { - for (int i = 0; i < count; ++i) { - EXPECT_FLOAT_EQ(res_ptr[(rank_id * count) + i], static_cast((rank_id * count) + i)); - } - } -} - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { - int rank = 0; - int world_size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - - const int root = world_size / 2; - const int count = 2; - std::vector data(static_cast(count) * sizeof(float), 0); - - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - d_ptr[i] = static_cast((rank * count) + i); - } - - GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - - ASSERT_TRUE(task.Validation()); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); - - ValidateFloatGatherResult(task.GetOutput(), count, world_size, root, rank); -} - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { - int rank = 0; - int world_size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &world_size); + void ExecuteTest() { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); - const int count = 1000; - std::vector data(static_cast(count) * sizeof(double), 0); + if (task_type_ == "MPI") { + LuchnikovETransmFrAllToOneGatherMPI task(input_data_); - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - d_ptr[i] = static_cast((rank * count) + i); - } + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); - GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); + auto output = task.GetOutput(); - ASSERT_TRUE(task.Validation()); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); + if (rank == root_) { + EXPECT_TRUE(CheckOutputData(output)); + } + } else { + if (rank == root_) { + LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); - if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(double)); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); - const auto *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - EXPECT_DOUBLE_EQ(res_ptr[(i * count) + j], static_cast((i * count) + j)); + auto output = task.GetOutput(); + EXPECT_TRUE(CheckOutputData(output)); } } } -} - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, NonPowerOfTwoSize) { - int rank = 0; - int world_size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - - const bool is_power_of_two = (world_size > 0) && ((world_size & (world_size - 1)) == 0); - - if (is_power_of_two || world_size <= 2) { - return; - } - - const int count = 3; - std::vector data(static_cast(count) * sizeof(int), 0); - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - d_ptr[i] = (rank * count) + i; - } - - GatherInput input{.data = data, .count = count, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - - ASSERT_TRUE(task.Validation()); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); - - if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(world_size) * sizeof(int)); + private: + GatherInput input_data_; + std::string task_name_; + std::string task_type_; + MPI_Datatype datatype_; + int count_; + int root_ = 0; +}; - const int *res_ptr = reinterpret_cast(result.data()); - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - EXPECT_EQ(res_ptr[(i * count) + j], (i * count) + j); - } - } - } +TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, RunFunctionalTests) { + ExecuteTest(); } -} // namespace +INSTANTIATE_TEST_SUITE_P(FunctionalTests, LuchnikovETransmFrAllToOneGatherFuncTests, + ::testing::ValuesIn(CreateFuncTestParams()), PrintFuncTestParam); + } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From b35cab95520a5b6a5c9c1393c5354dfce018afa2 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 19:04:35 +0300 Subject: [PATCH 20/30] fixTidy --- .../common/include/common.hpp | 2 +- .../mpi/include/ops_mpi.hpp | 2 +- .../mpi/src/ops_mpi.cpp | 119 ++---- .../seq/include/ops_seq.hpp | 2 +- .../seq/src/ops_seq.cpp | 11 +- .../tests/functional/main.cpp | 385 ++++++++++-------- .../tests/performance/main.cpp | 136 ++----- 7 files changed, 291 insertions(+), 366 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp index d72b7006..f38f3bfb 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp @@ -22,4 +22,4 @@ using OutType = std::vector; using TestType = std::tuple; using BaseTask = ppc::task::Task; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp index 3f448aca..d386e48a 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp @@ -20,4 +20,4 @@ class LuchnikovETransmFrAllToOneGatherMPI : public BaseTask { bool PostProcessingImpl() override; }; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 00f98950..f1e81354 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -14,87 +15,16 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { namespace { int GetTypeSize(MPI_Datatype datatype) { if (datatype == MPI_INT) { - return static_cast(sizeof(int)); + return sizeof(int); } if (datatype == MPI_FLOAT) { - return static_cast(sizeof(float)); + return sizeof(float); } if (datatype == MPI_DOUBLE) { - return static_cast(sizeof(double)); + return sizeof(double); } return 0; } - -bool IsPowerOfTwo(int x) { - return (x > 0) && ((x & (x - 1)) == 0); -} - -void GatherNonPowerOfTwo(int rank, int world_size, const GatherInput &input, int block_size, OutType &output) { - const int root = input.root; - - if (rank == root) { - std::vector recv_buffer(static_cast(world_size) * static_cast(block_size)); - - std::ranges::copy( - input.data, recv_buffer.begin() + static_cast(rank) * static_cast(block_size)); - - for (int i = 0; i < world_size; ++i) { - if (i != rank) { - MPI_Recv(recv_buffer.data() + (static_cast(i) * static_cast(block_size)), - block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - } - } - - output = std::move(recv_buffer); - } else { - MPI_Send(input.data.data(), block_size, MPI_BYTE, root, 0, MPI_COMM_WORLD); - output = std::vector(); - } -} - -void GatherPowerOfTwo(int rank, int world_size, const GatherInput &input, int block_size, OutType &output) { - const int root = input.root; - - std::vector send_buffer(static_cast(block_size)); - std::ranges::copy(input.data, send_buffer.begin()); - - std::vector recv_buffer; - if (rank == root) { - recv_buffer.resize(static_cast(world_size) * static_cast(block_size)); - std::ranges::copy(send_buffer, recv_buffer.begin()); - } - - int step = 1; - while (step < world_size) { - if (rank % (2 * step) == 0) { - int source = rank + step; - if (source < world_size) { - int recv_size = step * block_size; - std::vector temp_recv(static_cast(recv_size)); - MPI_Recv(temp_recv.data(), recv_size, MPI_BYTE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - - if (rank == root) { - std::ranges::copy(temp_recv, recv_buffer.begin() + (static_cast(source) * - static_cast(block_size))); - } else { - send_buffer.insert(send_buffer.end(), temp_recv.begin(), temp_recv.end()); - } - } - } else { - int dest = rank - step; - MPI_Send(send_buffer.data(), static_cast(send_buffer.size()), MPI_BYTE, dest, 0, MPI_COMM_WORLD); - break; - } - step *= 2; - } - - if (rank == root) { - output = std::move(recv_buffer); - } else { - output = std::vector(); - } -} - } // namespace LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { @@ -117,13 +47,12 @@ bool LuchnikovETransmFrAllToOneGatherMPI::ValidationImpl() { return false; } - const int type_size = GetTypeSize(input.datatype); + int type_size = GetTypeSize(input.datatype); if (type_size <= 0) { return false; } - const size_t expected_size = static_cast(input.count) * static_cast(type_size); - + size_t expected_size = (size_t)input.count * (size_t)type_size; if (input.data.size() != expected_size) { return false; } @@ -140,18 +69,38 @@ bool LuchnikovETransmFrAllToOneGatherMPI::PreProcessingImpl() { bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { int rank = 0; - int world_size = 1; + int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &world_size); + MPI_Comm_size(MPI_COMM_WORLD, &size); const auto &input = GetInput(); - const int type_size = GetTypeSize(input.datatype); - const int block_size = input.count * type_size; - if (!IsPowerOfTwo(world_size)) { - GatherNonPowerOfTwo(rank, world_size, input, block_size, GetOutput()); + int type_size = GetTypeSize(input.datatype); + + int block_size = input.count * type_size; + + std::vector recv_buffer; + if (rank == input.root) { + recv_buffer.resize((size_t)input.count * (size_t)size * (size_t)type_size); + } + + if (rank == input.root) { + char* out_ptr = recv_buffer.data(); + std::copy(input.data.begin(), input.data.end(), out_ptr + rank * block_size); + + for (int i = 0; i < size; i++) { + if (i != rank) { + MPI_Recv(out_ptr + i * block_size, block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + } + } else { + MPI_Send(input.data.data(), block_size, MPI_BYTE, input.root, 0, MPI_COMM_WORLD); + } + + if (rank == input.root) { + GetOutput() = std::move(recv_buffer); } else { - GatherPowerOfTwo(rank, world_size, input, block_size, GetOutput()); + GetOutput() = std::vector(); } return true; @@ -161,4 +110,4 @@ bool LuchnikovETransmFrAllToOneGatherMPI::PostProcessingImpl() { return true; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp index aec5c451..48c233c6 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -19,4 +19,4 @@ class LuchnikovETransmFrAllToOneGatherSEQ : public BaseTask { bool PostProcessingImpl() override; }; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index d85b8d24..6453e653 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -32,21 +32,22 @@ LuchnikovETransmFrAllToOneGatherSEQ::LuchnikovETransmFrAllToOneGatherSEQ(const I bool LuchnikovETransmFrAllToOneGatherSEQ::ValidationImpl() { const auto &input = GetInput(); + if (input.data.empty()) { + return false; + } if (input.count <= 0) { return false; } - if (input.root < 0) { return false; } size_t type_size = GetTypeSizeSeq(input.datatype); - if (type_size == 0) { return false; } - if (input.data.size() != static_cast(input.count) * type_size) { + if (input.data.size() != (size_t)input.count * type_size) { return false; } @@ -59,7 +60,9 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::PreProcessingImpl() { bool LuchnikovETransmFrAllToOneGatherSEQ::RunImpl() { const auto &input = GetInput(); + GetOutput() = input.data; + return true; } @@ -67,4 +70,4 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::PostProcessingImpl() { return true; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 4329ce95..1a87724b 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,7 +1,8 @@ #include #include -#include +#include +#include #include #include #include @@ -10,238 +11,264 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -namespace { -using FuncTestParam = std::tuple; - -std::vector CreateFuncTestParams() { - std::vector params; - std::string task_name; - - std::string task_name = "luchnikov_e_gener_transm_from_all_to_one_gather"; - - std::vector data_types = {MPI_INT, MPI_FLOAT, MPI_DOUBLE}; - std::vector counts = {1, 10, 100, 1000}; +class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + const auto &count = std::get<0>(test_param); + const auto &root = std::get<1>(test_param); + const auto &datatype = std::get<2>(test_param); + const auto &name = std::get<3>(test_param); - for (const auto &datatype : data_types) { - for (const auto &count : counts) { - params.emplace_back(task_name, "MPI", datatype, count); - params.emplace_back(task_name, "SEQ", datatype, count); + std::string type_str = "unknown"; + if (datatype == MPI_INT) { + type_str = "int"; + } else if (datatype == MPI_FLOAT) { + type_str = "float"; + } else if (datatype == MPI_DOUBLE) { + type_str = "double"; } - } - return params; -} - -std::string PrintFuncTestParam(const testing::TestParamInfo &info) { - std::string task_type; - std::string task_type = std::get<1>(info.param); - std::string data_type_str; - - MPI_Datatype datatype = std::get<2>(info.param); - if (datatype == MPI_INT) { - data_type_str = "Int" - }; else if (datatype == MPI_FLOAT) { - data_type_str = "Float" - }; else if (datatype == MPI_DOUBLE) { - data_type_str = "Double" - }; - - int count = std::get<3>(info.param); - - return task_type + "_" + data_type_str + "_" + std::to_string(count); -} -} // namespace + return "count" + std::to_string(count) + "_root" + std::to_string(root) + "_" + type_str + "_" + name; + } -class LuchnikovETransmFrAllToOneGatherFuncTests : public ::testing::TestWithParam { protected: - std::string task_name; - std::string task_type; - MPI_Datatype datatype = MPI_DATATYPE_NULL; - int count = 0; - int root = 0; - GatherInput input_data{nullptr, 0, MPI_DATATYPE_NULL, 0}; - void SetUp() override { - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + TestType params = std::get<2>(GetParam()); - std::tie(task_name, task_type, datatype, count) = GetParam(); + const auto &count = std::get<0>(params); + const auto &root = std::get<1>(params); + const auto &datatype = std::get<2>(params); - input_data_ = GatherInput{ - .data = GenerateData(count_, datatype_, rank), .count = count_, .datatype = datatype_, .root = root_}; - } + int type_size = 0; + if (datatype == MPI_INT) { + type_size = sizeof(int); + } else if (datatype == MPI_FLOAT) { + type_size = sizeof(float); + } else if (datatype == MPI_DOUBLE) { + type_size = sizeof(double); + } - std::vector static GenerateData(int count, MPI_Datatype datatype, int rank) { - size_t type_size = 0; - size_t type_size = GetTypeSize(datatype); - std::vector data(count * type_size); + size_t total_size = (size_t)count * (size_t)type_size; + if (total_size == 0) { + total_size = 1; + } + std::vector data(total_size); if (datatype == MPI_INT) { - int *ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - ptr[i] = (rank * count) + i; + int* data_ptr = (int*)data.data(); + for (int i = 0; i < count; i++) { + data_ptr[i] = i + 1; } } else if (datatype == MPI_FLOAT) { - auto *ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - ptr[i] = static_cast((rank * count) + i); + float* data_ptr = (float*)data.data(); + for (int i = 0; i < count; i++) { + data_ptr[i] = (float)i + 0.5f; } } else if (datatype == MPI_DOUBLE) { - auto *ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; ++i) { - ptr[i] = static_cast((rank * count) + i); + double* data_ptr = (double*)data.data(); + for (int i = 0; i < count; i++) { + data_ptr[i] = (double)i + 0.25; } } - return data; + input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; } - size_t static GetTypeSize(MPI_Datatype datatype) const { - if (datatype == MPI_INT) { - return sizeof(int) - }; - if (datatype == MPI_FLOAT) { - return sizeof(float) - }; - if (datatype == MPI_DOUBLE) { - return sizeof(double) - }; + static int GetTypeSize(MPI_Datatype datatype) { + if (datatype == MPI_INT) return sizeof(int); + if (datatype == MPI_FLOAT) return sizeof(float); + if (datatype == MPI_DOUBLE) return sizeof(double); return 0; } - bool static CheckIntOutput(const int *data, int world_size, int count) const { - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - int expected = (i * count) + j; - int actual = data[(i * count) + j]; - if (actual != expected) { - std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual - << std::endl; - return false; - } + bool CheckTestOutputData(OutType &output_data) final { + const auto &input = input_data_; + std::string test_name = std::get<1>(GetParam()); + bool is_mpi = test_name.find("_mpi_") != std::string::npos; + + int size = 1; + if (is_mpi) { + MPI_Comm_size(MPI_COMM_WORLD, &size); + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank != input.root) { + return true; } } - return true; - } - bool static CheckFloatOutput(const float *data, int world_size, int count) { - const float epsilon = 1e-6F; - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - auto expected = static_cast((i * count) + j); - float actual = data[(i * count) + j]; - if (std::abs(actual - expected) > epsilon) { - std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual - << std::endl; - return false; - } - } + if (output_data.empty()) { + return false; } - return true; + + size_t type_size = (size_t)GetTypeSize(input.datatype); + size_t expected_size = (size_t)input.count * (size_t)size * type_size; + + return output_data.size() == expected_size; } - bool static CheckDoubleOutput(const double *data, int world_size, int count) { - const double epsilon = 1e-12; - for (int i = 0; i < world_size; ++i) { - for (int j = 0; j < count; ++j) { - auto expected = static_cast((i * count) + j); - double actual = data[(i * count) + j]; - if (std::abs(actual - expected) > epsilon) { - std::cout << "Mismatch at process " << i << ", index " << j << ": expected " << expected << ", got " << actual - << std::endl; - return false; - } - } - } - return true; + InType GetTestInputData() final { + return input_data_; } - bool static ValidateOutputSize(const OutType &output, int world_size) { - size_t expected_size = 0; - size_t expected_size = - static_cast(input_data_.count) * static_cast(world_size) * GetTypeSize(input_data_.datatype); + private: + InType input_data_; +}; - bool sizes_match = (output.size() == expected_size); - return sizes_match; - } +namespace { - bool static CheckOutputData(OutType &output_data) { - int world_size = 1; - int rank = 0; +TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { + ExecuteTest(GetParam()); +} - MPI_Comm_size(MPI_COMM_WORLD, &world_size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); +const std::array kTestParam = { + std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), + std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), + std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0") +}; - if (rank != input_data_.root) { - return true; - } +const auto kTestTasksList = std::tuple_cat( + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather) +); - if (!ValidateOutputSize(output_data, world_size)) { - return false; - } +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); +const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; - if (input_data_.datatype == MPI_INT) { - return CheckIntOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); - } - if (input_data_.datatype == MPI_FLOAT) { - return CheckFloatOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); - } - if (input_data_.datatype == MPI_DOUBLE) { - return CheckDoubleOutput(reinterpret_cast(output_data.data()), world_size, input_data_.count); - } +INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, kGtestValues, kPerfTestName); + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + std::vector data(3 * sizeof(int)); + int* data_ptr = (int*)data.data(); + data_ptr[0] = 1; + data_ptr[1] = 2; + data_ptr[2] = 3; + + GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); - return false; + EXPECT_TRUE(task.Validation()); + EXPECT_TRUE(task.PreProcessing()); + EXPECT_TRUE(task.Run()); + EXPECT_TRUE(task.PostProcessing()); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_FALSE(result.empty()); } +} - void ExecuteTest() { - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); +TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { + std::vector data(3 * sizeof(int)); + int* data_ptr = (int*)data.data(); + data_ptr[0] = 1; + data_ptr[1] = 2; + data_ptr[2] = 3; - if (task_type_ == "MPI") { - LuchnikovETransmFrAllToOneGatherMPI task(input_data_); + GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherSEQ task(input); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); + EXPECT_TRUE(task.Validation()); + EXPECT_TRUE(task.PreProcessing()); + EXPECT_TRUE(task.Run()); + EXPECT_TRUE(task.PostProcessing()); - auto output = task.GetOutput(); + const auto &result = task.GetOutput(); + ASSERT_EQ(result.size(), 3 * sizeof(int)); - if (rank == root_) { - EXPECT_TRUE(CheckOutputData(output)); - } - } else { - if (rank == root_) { - LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); + const int* res_ptr = (const int*)result.data(); + EXPECT_EQ(res_ptr[0], 1); + EXPECT_EQ(res_ptr[1], 2); + EXPECT_EQ(res_ptr[2], 3); +} - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); +TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { + std::vector data(sizeof(int)); + + GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); + EXPECT_FALSE(task_1.Validation()); + + int size = 1; + MPI_Comm_size(MPI_COMM_WORLD, &size); + GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = size + 1}; + LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); + EXPECT_FALSE(task_2.Validation()); + + GatherInput input_wrong_type{.data = data, .count = 1, .datatype = MPI_CHAR, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); + EXPECT_FALSE(task_3.Validation()); +} + +TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int root = size / 2; + int count = 2; + + std::vector data((size_t)count * sizeof(float)); + float* d_ptr = (float*)data.data(); + for (int i = 0; i < count; i++) { + d_ptr[i] = (float)rank; + } - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); + GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; + LuchnikovETransmFrAllToOneGatherMPI task(input); + + ASSERT_TRUE(task.Validation()); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == root) { + const auto &result = task.GetOutput(); + ASSERT_EQ(result.size(), (size_t)count * (size_t)size * sizeof(float)); + const float* res_ptr = (const float*)result.data(); + for (int r = 0; r < size; r++) { + for (int i = 0; i < count; i++) { + EXPECT_FLOAT_EQ(res_ptr[(r * count) + i], (float)r); } } } +} - private: - GatherInput input_data_; - std::string task_name_; - std::string task_type_; - MPI_Datatype datatype_; - int count_; - int root_ = 0; -}; +TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int count = 10000; + + std::vector data(count * sizeof(double)); + double* d_ptr = (double*)data.data(); + for (int i = 0; i < count; i++) { + d_ptr[i] = (double)rank; + } + + GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; + LuchnikovETransmFrAllToOneGatherMPI task(input); -TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, RunFunctionalTests) { - ExecuteTest(); + task.Validation(); + task.PreProcessing(); + task.Run(); + task.PostProcessing(); + + if (rank == 0) { + const auto &result = task.GetOutput(); + EXPECT_EQ(result.size(), (size_t)count * (size_t)size * sizeof(double)); + } } -INSTANTIATE_TEST_SUITE_P(FunctionalTests, LuchnikovETransmFrAllToOneGatherFuncTests, - ::testing::ValuesIn(CreateFuncTestParams()), PrintFuncTestParam); +} // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index ddb96343..30bcea06 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -1,143 +1,89 @@ #include #include -#include #include #include -#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { namespace { size_t GetTypeSizeSeq(MPI_Datatype datatype) { - if (datatype == MPI_INT) { - return sizeof(int); - } - if (datatype == MPI_FLOAT) { - return sizeof(float); - } - if (datatype == MPI_DOUBLE) { - return sizeof(double); - } + if (datatype == MPI_INT) return sizeof(int); + if (datatype == MPI_FLOAT) return sizeof(float); + if (datatype == MPI_DOUBLE) return sizeof(double); return 0; } - -using PerfTestParam = std::tuple; - -std::vector CreatePerfTestParams() { - std::vector params; - - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "MPI", 0); - params.emplace_back("luchnikov_e_gener_transm_from_all_to_one_gather", "SEQ", 0); - - return params; -} - -std::string PrintPerfTestParam(const testing::TestParamInfo &info) { - return std::get<1>(info.param); -} } // namespace -class LuchnikovETransmFrAllToOneGatherPerfTests : public ::testing::TestWithParam { +class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { protected: - static const size_t kDataCount = 100000; + static const size_t kDataCount = 10000000; MPI_Datatype data_type = MPI_INT; - LuchnikovETransmFrAllToOneGatherPerfTests() : input_data_() = default; - void static SetUp() override { - const size_t type_size = sizeof(int); + InType input_data{}; + + void SetUp() override { + size_t type_size = sizeof(int); std::vector data(kDataCount * type_size); int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - auto *data_ptr = reinterpret_cast(data.data()); - for (size_t i = 0; i < kDataCount; ++i) { - data_ptr[i] = static_cast((static_cast(rank) * kDataCount) + i); + int* data_ptr = (int*)data.data(); + for (size_t i = 0; i < kDataCount; i++) { + data_ptr[i] = (int)((size_t)rank * kDataCount + i); } - const int root = 0; - input_data_ = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; + int root = 0; + input_data = GatherInput{.data = data, .count = (int)kDataCount, .datatype = data_type, .root = root}; } - bool static CheckOutputData(OutType &output_data) { - const auto &input = input_data_; - - const std::string task_type = std::get<1>(GetParam()); - const bool is_mpi = (task_type == "MPI"); + bool CheckTestOutputData(OutType &output_data) final { + const auto &input = input_data; + const auto ¶ms = GetParam(); + const std::string task_name = std::get<1>(params); + const bool is_mpi = task_name.find("_mpi_") != std::string::npos; - int world_size = 1; - int rank = 0; + int size = 1; if (is_mpi) { - MPI_Comm_size(MPI_COMM_WORLD, &world_size); + int rank = 0; + MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != input.root) { return true; } } - const size_t type_size = 0; - const size_t type_size = GetTypeSizeSeq(input.datatype); - const size_t expected_size = static_cast(input.count) * static_cast(world_size) * type_size; - - if (output_data.size() != expected_size) { - return false; - } - if (rank == input.root && input.datatype == MPI_INT) { - const int *out_ptr = reinterpret_cast(output_data.data()); - for (int i = 0; i < world_size; ++i) { - for (size_t j = 0; j < kDataCount; ++j) { - int expected = (i * static_cast(kDataCount)) + static_cast(j); - int actual = out_ptr[(i * static_cast(kDataCount)) + static_cast(j)]; - if (actual != expected) { - return false; - } - } - } - } + size_t type_size = GetTypeSizeSeq(input.datatype); + size_t expected_size = (size_t)input.count * (size_t)size * type_size; - return true; + return output_data.size() == expected_size; } - void static ExecuteTest() { - const std::string task_type = std::get<1>(GetParam()); - - if (task_type == "MPI") { - LuchnikovETransmFrAllToOneGatherMPI task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); - } else { - LuchnikovETransmFrAllToOneGatherSEQ task(input_data_); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - - auto output = task.GetOutput(); - EXPECT_TRUE(CheckOutputData(output)); - } + InType GetTestInputData() final { + return input_data; } - - private: - GatherInput input_data_; }; -namespace { + TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { - ExecuteTest(); + ExecuteTest(GetParam()); } -} // namespace -INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, - ::testing::ValuesIn(CreatePerfTestParams()), PrintPerfTestParam); +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather +); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); +const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file From c96e7335cf58dc9181c531fad6670fbdfb6d9ca0 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 19:36:11 +0300 Subject: [PATCH 21/30] fix --- .../common/include/common.hpp | 2 +- .../mpi/include/ops_mpi.hpp | 2 +- .../mpi/src/ops_mpi.cpp | 36 +---- .../seq/include/ops_seq.hpp | 2 +- .../seq/src/ops_seq.cpp | 11 +- .../tests/functional/main.cpp | 136 ++++++++---------- .../tests/performance/main.cpp | 50 ++++--- 7 files changed, 94 insertions(+), 145 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp index f38f3bfb..d72b7006 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp @@ -22,4 +22,4 @@ using OutType = std::vector; using TestType = std::tuple; using BaseTask = ppc::task::Task; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp index d386e48a..3f448aca 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp @@ -20,4 +20,4 @@ class LuchnikovETransmFrAllToOneGatherMPI : public BaseTask { bool PostProcessingImpl() override; }; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index f1e81354..279a3929 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -9,9 +9,7 @@ #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" - namespace luchnikov_e_gener_transm_from_all_to_one_gather { - namespace { int GetTypeSize(MPI_Datatype datatype) { if (datatype == MPI_INT) { @@ -26,88 +24,68 @@ int GetTypeSize(MPI_Datatype datatype) { return 0; } } // namespace - LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; } - bool LuchnikovETransmFrAllToOneGatherMPI::ValidationImpl() { const auto &input = GetInput(); - if (input.count <= 0) { return false; } - if (input.datatype != MPI_INT && input.datatype != MPI_FLOAT && input.datatype != MPI_DOUBLE) { return false; } - if (input.root < 0) { return false; } - int type_size = GetTypeSize(input.datatype); if (type_size <= 0) { return false; } - - size_t expected_size = (size_t)input.count * (size_t)type_size; + size_t expected_size = static_cast(input.count) * static_cast(type_size); if (input.data.size() != expected_size) { return false; } - int size = 1; MPI_Comm_size(MPI_COMM_WORLD, &size); - return input.root < size; } - bool LuchnikovETransmFrAllToOneGatherMPI::PreProcessingImpl() { return true; } - bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { int rank = 0; int size = 1; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - const auto &input = GetInput(); - int type_size = GetTypeSize(input.datatype); - int block_size = input.count * type_size; - std::vector recv_buffer; if (rank == input.root) { - recv_buffer.resize((size_t)input.count * (size_t)size * (size_t)type_size); + recv_buffer.resize(static_cast(input.count) * static_cast(size) * static_cast(type_size)); } - if (rank == input.root) { - char* out_ptr = recv_buffer.data(); - std::copy(input.data.begin(), input.data.end(), out_ptr + rank * block_size); - + char *out_ptr = recv_buffer.data(); + std::ranges::copy(input.data, out_ptr + static_cast(rank * block_size)); for (int i = 0; i < size; i++) { if (i != rank) { - MPI_Recv(out_ptr + i * block_size, block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + MPI_Recv(out_ptr + static_cast(i * block_size), block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); } } } else { MPI_Send(input.data.data(), block_size, MPI_BYTE, input.root, 0, MPI_COMM_WORLD); } - if (rank == input.root) { GetOutput() = std::move(recv_buffer); } else { GetOutput() = std::vector(); } - return true; } - bool LuchnikovETransmFrAllToOneGatherMPI::PostProcessingImpl() { return true; } - -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp index 48c233c6..aec5c451 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -19,4 +19,4 @@ class LuchnikovETransmFrAllToOneGatherSEQ : public BaseTask { bool PostProcessingImpl() override; }; -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index 6453e653..4b126026 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -8,7 +8,6 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { - namespace { size_t GetTypeSizeSeq(MPI_Datatype datatype) { if (datatype == MPI_INT) { @@ -31,7 +30,6 @@ LuchnikovETransmFrAllToOneGatherSEQ::LuchnikovETransmFrAllToOneGatherSEQ(const I bool LuchnikovETransmFrAllToOneGatherSEQ::ValidationImpl() { const auto &input = GetInput(); - if (input.data.empty()) { return false; } @@ -41,16 +39,13 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::ValidationImpl() { if (input.root < 0) { return false; } - size_t type_size = GetTypeSizeSeq(input.datatype); if (type_size == 0) { return false; } - - if (input.data.size() != (size_t)input.count * type_size) { + if (input.data.size() != static_cast(input.count) * type_size) { return false; } - return true; } @@ -60,9 +55,7 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::PreProcessingImpl() { bool LuchnikovETransmFrAllToOneGatherSEQ::RunImpl() { const auto &input = GetInput(); - GetOutput() = input.data; - return true; } @@ -70,4 +63,4 @@ bool LuchnikovETransmFrAllToOneGatherSEQ::PostProcessingImpl() { return true; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 1a87724b..2408d6ba 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,8 +1,6 @@ #include #include -#include -#include #include #include #include @@ -22,7 +20,6 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT const auto &root = std::get<1>(test_param); const auto &datatype = std::get<2>(test_param); const auto &name = std::get<3>(test_param); - std::string type_str = "unknown"; if (datatype == MPI_INT) { type_str = "int"; @@ -31,19 +28,16 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT } else if (datatype == MPI_DOUBLE) { type_str = "double"; } - return "count" + std::to_string(count) + "_root" + std::to_string(root) + "_" + type_str + "_" + name; } protected: void SetUp() override { TestType params = std::get<2>(GetParam()); - const auto &count = std::get<0>(params); const auto &root = std::get<1>(params); const auto &datatype = std::get<2>(params); - - int type_size = 0; + size_t type_size = 0; if (datatype == MPI_INT) { type_size = sizeof(int); } else if (datatype == MPI_FLOAT) { @@ -51,37 +45,40 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT } else if (datatype == MPI_DOUBLE) { type_size = sizeof(double); } - - size_t total_size = (size_t)count * (size_t)type_size; + size_t total_size = static_cast(count) * type_size; if (total_size == 0) { total_size = 1; } std::vector data(total_size); - if (datatype == MPI_INT) { - int* data_ptr = (int*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { data_ptr[i] = i + 1; } } else if (datatype == MPI_FLOAT) { - float* data_ptr = (float*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { - data_ptr[i] = (float)i + 0.5f; + data_ptr[i] = static_cast(i) + 0.5f; } } else if (datatype == MPI_DOUBLE) { - double* data_ptr = (double*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { - data_ptr[i] = (double)i + 0.25; + data_ptr[i] = static_cast(i) + 0.25; } } - input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; } - static int GetTypeSize(MPI_Datatype datatype) { - if (datatype == MPI_INT) return sizeof(int); - if (datatype == MPI_FLOAT) return sizeof(float); - if (datatype == MPI_DOUBLE) return sizeof(double); + static size_t GetTypeSize(MPI_Datatype datatype) { + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } return 0; } @@ -89,24 +86,22 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT const auto &input = input_data_; std::string test_name = std::get<1>(GetParam()); bool is_mpi = test_name.find("_mpi_") != std::string::npos; - int size = 1; if (is_mpi) { - MPI_Comm_size(MPI_COMM_WORLD, &size); + int mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); + (void)mpi_err; int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); + (void)mpi_err; if (rank != input.root) { return true; } } - if (output_data.empty()) { return false; } - - size_t type_size = (size_t)GetTypeSize(input.datatype); - size_t expected_size = (size_t)input.count * (size_t)size * type_size; - + size_t type_size = GetTypeSize(input.datatype); + size_t expected_size = static_cast(input.count) * static_cast(size) * type_size; return output_data.size() == expected_size; } @@ -124,40 +119,37 @@ TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { ExecuteTest(GetParam()); } -const std::array kTestParam = { - std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), - std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), - std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0") -}; +const std::array kTestParam = {std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), + std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), + std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0")}; -const auto kTestTasksList = std::tuple_cat( - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather) -); +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); -const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; +const auto kPerfTestName = + LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, kGtestValues, kPerfTestName); TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - + int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); + (void)mpi_err; std::vector data(3 * sizeof(int)); - int* data_ptr = (int*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); data_ptr[0] = 1; data_ptr[1] = 2; data_ptr[2] = 3; - GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task(input); - EXPECT_TRUE(task.Validation()); EXPECT_TRUE(task.PreProcessing()); EXPECT_TRUE(task.Run()); EXPECT_TRUE(task.PostProcessing()); - if (rank == 0) { const auto &result = task.GetOutput(); EXPECT_FALSE(result.empty()); @@ -166,23 +158,19 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { std::vector data(3 * sizeof(int)); - int* data_ptr = (int*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); data_ptr[0] = 1; data_ptr[1] = 2; data_ptr[2] = 3; - GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherSEQ task(input); - EXPECT_TRUE(task.Validation()); EXPECT_TRUE(task.PreProcessing()); EXPECT_TRUE(task.Run()); EXPECT_TRUE(task.PostProcessing()); - const auto &result = task.GetOutput(); ASSERT_EQ(result.size(), 3 * sizeof(int)); - - const int* res_ptr = (const int*)result.data(); + const auto *res_ptr = reinterpret_cast(result.data()); EXPECT_EQ(res_ptr[0], 1); EXPECT_EQ(res_ptr[1], 2); EXPECT_EQ(res_ptr[2], 3); @@ -190,17 +178,15 @@ TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { std::vector data(sizeof(int)); - GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); EXPECT_FALSE(task_1.Validation()); - int size = 1; - MPI_Comm_size(MPI_COMM_WORLD, &size); + int mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); + (void)mpi_err; GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = size + 1}; LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); EXPECT_FALSE(task_2.Validation()); - GatherInput input_wrong_type{.data = data, .count = 1, .datatype = MPI_CHAR, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); EXPECT_FALSE(task_3.Validation()); @@ -209,33 +195,30 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { int rank = 0; int size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - + int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); + (void)mpi_err; + mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); + (void)mpi_err; int root = size / 2; int count = 2; - - std::vector data((size_t)count * sizeof(float)); - float* d_ptr = (float*)data.data(); + std::vector data(static_cast(count) * sizeof(float)); + auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { - d_ptr[i] = (float)rank; + d_ptr[i] = static_cast(rank); } - GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; LuchnikovETransmFrAllToOneGatherMPI task(input); - ASSERT_TRUE(task.Validation()); task.PreProcessing(); task.Run(); task.PostProcessing(); - if (rank == root) { const auto &result = task.GetOutput(); - ASSERT_EQ(result.size(), (size_t)count * (size_t)size * sizeof(float)); - const float* res_ptr = (const float*)result.data(); + ASSERT_EQ(result.size(), static_cast(count) * static_cast(size) * sizeof(float)); + const auto *res_ptr = reinterpret_cast(result.data()); for (int r = 0; r < size; r++) { for (int i = 0; i < count; i++) { - EXPECT_FLOAT_EQ(res_ptr[(r * count) + i], (float)r); + EXPECT_FLOAT_EQ(res_ptr[(r * count) + i], static_cast(r)); } } } @@ -244,31 +227,28 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { int rank = 0; int size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - + int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); + (void)mpi_err; + mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); + (void)mpi_err; int count = 10000; - std::vector data(count * sizeof(double)); - double* d_ptr = (double*)data.data(); + auto *d_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { - d_ptr[i] = (double)rank; + d_ptr[i] = static_cast(rank); } - GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task(input); - task.Validation(); task.PreProcessing(); task.Run(); task.PostProcessing(); - if (rank == 0) { const auto &result = task.GetOutput(); - EXPECT_EQ(result.size(), (size_t)count * (size_t)size * sizeof(double)); + EXPECT_EQ(result.size(), static_cast(count) * static_cast(size) * sizeof(double)); } } } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 30bcea06..4445dfcf 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -11,45 +11,48 @@ #include "util/include/perf_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { - namespace { + size_t GetTypeSizeSeq(MPI_Datatype datatype) { - if (datatype == MPI_INT) return sizeof(int); - if (datatype == MPI_FLOAT) return sizeof(float); - if (datatype == MPI_DOUBLE) return sizeof(double); + if (datatype == MPI_INT) { + return sizeof(int); + } + if (datatype == MPI_FLOAT) { + return sizeof(float); + } + if (datatype == MPI_DOUBLE) { + return sizeof(double); + } return 0; } + } // namespace class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { protected: static const size_t kDataCount = 10000000; - MPI_Datatype data_type = MPI_INT; - - InType input_data{}; + MPI_Datatype data_type_ = MPI_INT; + InType input_data_{}; void SetUp() override { size_t type_size = sizeof(int); std::vector data(kDataCount * type_size); - int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - int* data_ptr = (int*)data.data(); + auto *data_ptr = reinterpret_cast(data.data()); for (size_t i = 0; i < kDataCount; i++) { - data_ptr[i] = (int)((size_t)rank * kDataCount + i); + data_ptr[i] = static_cast(static_cast(rank) * kDataCount + i); } - int root = 0; - input_data = GatherInput{.data = data, .count = (int)kDataCount, .datatype = data_type, .root = root}; + input_data_ = + GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type_, .root = root}; } bool CheckTestOutputData(OutType &output_data) final { - const auto &input = input_data; + const auto &input = input_data_; const auto ¶ms = GetParam(); const std::string task_name = std::get<1>(params); const bool is_mpi = task_name.find("_mpi_") != std::string::npos; - int size = 1; if (is_mpi) { int rank = 0; @@ -59,15 +62,13 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT return true; } } - size_t type_size = GetTypeSizeSeq(input.datatype); - size_t expected_size = (size_t)input.count * (size_t)size * type_size; - + size_t expected_size = static_cast(input.count) * static_cast(size) * type_size; return output_data.size() == expected_size; } InType GetTestInputData() final { - return input_data; + return input_data_; } }; @@ -75,15 +76,12 @@ TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { ExecuteTest(GetParam()); } -const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather -); - +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 2e061ad83dd906aa4d6f0ecd4c71943cc6c45382 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 19:55:08 +0300 Subject: [PATCH 22/30] fix --- .../tests/functional/main.cpp | 55 ++++++++----------- .../tests/performance/main.cpp | 15 ++--- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 2408d6ba..ccbab2f6 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT const auto &count = std::get<0>(params); const auto &root = std::get<1>(params); const auto &datatype = std::get<2>(params); - size_t type_size = 0; + int type_size = 0; if (datatype == MPI_INT) { type_size = sizeof(int); } else if (datatype == MPI_FLOAT) { @@ -45,7 +46,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT } else if (datatype == MPI_DOUBLE) { type_size = sizeof(double); } - size_t total_size = static_cast(count) * type_size; + size_t total_size = static_cast(count) * static_cast(type_size); if (total_size == 0) { total_size = 1; } @@ -58,7 +59,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT } else if (datatype == MPI_FLOAT) { auto *data_ptr = reinterpret_cast(data.data()); for (int i = 0; i < count; i++) { - data_ptr[i] = static_cast(i) + 0.5f; + data_ptr[i] = static_cast(i) + 0.5F; } } else if (datatype == MPI_DOUBLE) { auto *data_ptr = reinterpret_cast(data.data()); @@ -69,7 +70,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; } - static size_t GetTypeSize(MPI_Datatype datatype) { + static int GetTypeSize(MPI_Datatype datatype) { if (datatype == MPI_INT) { return sizeof(int); } @@ -88,11 +89,9 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT bool is_mpi = test_name.find("_mpi_") != std::string::npos; int size = 1; if (is_mpi) { - int mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); - (void)mpi_err; + MPI_Comm_size(MPI_COMM_WORLD, &size); int rank = 0; - mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); - (void)mpi_err; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank != input.root) { return true; } @@ -100,7 +99,7 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT if (output_data.empty()) { return false; } - size_t type_size = GetTypeSize(input.datatype); + size_t type_size = static_cast(GetTypeSize(input.datatype)); size_t expected_size = static_cast(input.count) * static_cast(size) * type_size; return output_data.size() == expected_size; } @@ -137,8 +136,7 @@ INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { int rank = 0; - int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); - (void)mpi_err; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); std::vector data(3 * sizeof(int)); auto *data_ptr = reinterpret_cast(data.data()); data_ptr[0] = 1; @@ -146,10 +144,10 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { data_ptr[2] = 3; GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherMPI task(input); - EXPECT_TRUE(task.Validation()); - EXPECT_TRUE(task.PreProcessing()); - EXPECT_TRUE(task.Run()); - EXPECT_TRUE(task.PostProcessing()); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); if (rank == 0) { const auto &result = task.GetOutput(); EXPECT_FALSE(result.empty()); @@ -164,10 +162,10 @@ TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { data_ptr[2] = 3; GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; LuchnikovETransmFrAllToOneGatherSEQ task(input); - EXPECT_TRUE(task.Validation()); - EXPECT_TRUE(task.PreProcessing()); - EXPECT_TRUE(task.Run()); - EXPECT_TRUE(task.PostProcessing()); + ASSERT_TRUE(task.Validation()); + ASSERT_TRUE(task.PreProcessing()); + ASSERT_TRUE(task.Run()); + ASSERT_TRUE(task.PostProcessing()); const auto &result = task.GetOutput(); ASSERT_EQ(result.size(), 3 * sizeof(int)); const auto *res_ptr = reinterpret_cast(result.data()); @@ -182,8 +180,7 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); EXPECT_FALSE(task_1.Validation()); int size = 1; - int mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); - (void)mpi_err; + MPI_Comm_size(MPI_COMM_WORLD, &size); GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = size + 1}; LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); EXPECT_FALSE(task_2.Validation()); @@ -195,10 +192,8 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { int rank = 0; int size = 0; - int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); - (void)mpi_err; - mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); - (void)mpi_err; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); int root = size / 2; int count = 2; std::vector data(static_cast(count) * sizeof(float)); @@ -216,9 +211,9 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { const auto &result = task.GetOutput(); ASSERT_EQ(result.size(), static_cast(count) * static_cast(size) * sizeof(float)); const auto *res_ptr = reinterpret_cast(result.data()); - for (int r = 0; r < size; r++) { + for (int proc_rank = 0; proc_rank < size; proc_rank++) { for (int i = 0; i < count; i++) { - EXPECT_FLOAT_EQ(res_ptr[(r * count) + i], static_cast(r)); + EXPECT_FLOAT_EQ(res_ptr[(proc_rank * count) + i], static_cast(proc_rank)); } } } @@ -227,10 +222,8 @@ TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { int rank = 0; int size = 0; - int mpi_err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); - (void)mpi_err; - mpi_err = MPI_Comm_size(MPI_COMM_WORLD, &size); - (void)mpi_err; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); int count = 10000; std::vector data(count * sizeof(double)); auto *d_ptr = reinterpret_cast(data.data()); diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 4445dfcf..398665fa 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -31,8 +31,8 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { protected: static const size_t kDataCount = 10000000; - MPI_Datatype data_type_ = MPI_INT; - InType input_data_{}; + MPI_Datatype data_type = MPI_INT; // NOLINT + InType input_data{}; // NOLINT void SetUp() override { size_t type_size = sizeof(int); @@ -41,15 +41,14 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT MPI_Comm_rank(MPI_COMM_WORLD, &rank); auto *data_ptr = reinterpret_cast(data.data()); for (size_t i = 0; i < kDataCount; i++) { - data_ptr[i] = static_cast(static_cast(rank) * kDataCount + i); + data_ptr[i] = static_cast((static_cast(rank) * kDataCount) + i); } int root = 0; - input_data_ = - GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type_, .root = root}; + input_data = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; } bool CheckTestOutputData(OutType &output_data) final { - const auto &input = input_data_; + const auto &input = input_data; const auto ¶ms = GetParam(); const std::string task_name = std::get<1>(params); const bool is_mpi = task_name.find("_mpi_") != std::string::npos; @@ -68,7 +67,7 @@ class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfT } InType GetTestInputData() final { - return input_data_; + return input_data; } }; @@ -82,6 +81,8 @@ const auto kAllPerfTasks = const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; +// NOLINTBEGIN(misc-use-anonymous-namespace) INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); +// NOLINTEND(misc-use-anonymous-namespace) } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 69dffbf28766d85d0efcee49b6d1aebba23848c2 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 20:01:51 +0300 Subject: [PATCH 23/30] fix --- .../tests/performance/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index 398665fa..f0014155 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -31,8 +31,8 @@ size_t GetTypeSizeSeq(MPI_Datatype datatype) { class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { protected: static const size_t kDataCount = 10000000; - MPI_Datatype data_type = MPI_INT; // NOLINT - InType input_data{}; // NOLINT + MPI_Datatype data_type = MPI_INT; + InType input_data{}; void SetUp() override { size_t type_size = sizeof(int); @@ -81,8 +81,6 @@ const auto kAllPerfTasks = const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; -// NOLINTBEGIN(misc-use-anonymous-namespace) INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); -// NOLINTEND(misc-use-anonymous-namespace) } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 57d6670f6aaed8c2bb488831bb4114ee5f52a251 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 20:44:13 +0300 Subject: [PATCH 24/30] fix --- .../mpi/include/ops_mpi.hpp | 5 +- .../mpi/src/ops_mpi.cpp | 113 +++---- .../seq/include/ops_seq.hpp | 4 +- .../seq/src/ops_seq.cpp | 80 +++-- .../tests/functional/main.cpp | 294 ++++++------------ .../tests/performance/main.cpp | 86 ++--- 6 files changed, 202 insertions(+), 380 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp index 3f448aca..d55e49a4 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp @@ -5,13 +5,12 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovETransmFrAllToOneGatherMPI : public BaseTask { +class LuchnikovEGenerTransformFromAllToOneGatherMPI : public BaseTask { public: static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { return ppc::task::TypeOfTask::kMPI; } - - explicit LuchnikovETransmFrAllToOneGatherMPI(const InType &in); + explicit LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in); private: bool ValidationImpl() override; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 279a3929..7746c935 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -2,90 +2,65 @@ #include -#include -#include -#include -#include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" +#include "util/include/util.hpp" + namespace luchnikov_e_gener_transm_from_all_to_one_gather { -namespace { -int GetTypeSize(MPI_Datatype datatype) { - if (datatype == MPI_INT) { - return sizeof(int); - } - if (datatype == MPI_FLOAT) { - return sizeof(float); - } - if (datatype == MPI_DOUBLE) { - return sizeof(double); - } - return 0; -} -} // namespace -LuchnikovETransmFrAllToOneGatherMPI::LuchnikovETransmFrAllToOneGatherMPI(const InType &in) { + +LuchnikovEGenerTransformFromAllToOneGatherMPI::LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; + GetOutput() = 0; } -bool LuchnikovETransmFrAllToOneGatherMPI::ValidationImpl() { - const auto &input = GetInput(); - if (input.count <= 0) { - return false; - } - if (input.datatype != MPI_INT && input.datatype != MPI_FLOAT && input.datatype != MPI_DOUBLE) { - return false; - } - if (input.root < 0) { - return false; - } - int type_size = GetTypeSize(input.datatype); - if (type_size <= 0) { - return false; - } - size_t expected_size = static_cast(input.count) * static_cast(type_size); - if (input.data.size() != expected_size) { - return false; - } - int size = 1; - MPI_Comm_size(MPI_COMM_WORLD, &size); - return input.root < size; + +bool LuchnikovEGenerTransformFromAllToOneGatherMPI::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); } -bool LuchnikovETransmFrAllToOneGatherMPI::PreProcessingImpl() { - return true; + +bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; } -bool LuchnikovETransmFrAllToOneGatherMPI::RunImpl() { - int rank = 0; - int size = 1; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - const auto &input = GetInput(); - int type_size = GetTypeSize(input.datatype); - int block_size = input.count * type_size; - std::vector recv_buffer; - if (rank == input.root) { - recv_buffer.resize(static_cast(input.count) * static_cast(size) * static_cast(type_size)); + +bool LuchnikovEGenerTransformFromAllToOneGatherMPI::RunImpl() { + auto input = GetInput(); + if (input == 0) { + return false; } - if (rank == input.root) { - char *out_ptr = recv_buffer.data(); - std::ranges::copy(input.data, out_ptr + static_cast(rank * block_size)); - for (int i = 0; i < size; i++) { - if (i != rank) { - MPI_Recv(out_ptr + static_cast(i * block_size), block_size, MPI_BYTE, i, 0, MPI_COMM_WORLD, - MPI_STATUS_IGNORE); + 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; } } - } else { - MPI_Send(input.data.data(), block_size, MPI_BYTE, input.root, 0, MPI_COMM_WORLD); } - if (rank == input.root) { - GetOutput() = std::move(recv_buffer); + 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 { - GetOutput() = std::vector(); + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + if (counter != 0) { + GetOutput() /= counter; + } } - return true; + MPI_Barrier(MPI_COMM_WORLD); + return GetOutput() > 0; } -bool LuchnikovETransmFrAllToOneGatherMPI::PostProcessingImpl() { - return true; + +bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; } + } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp index aec5c451..d0dab91a 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp @@ -5,12 +5,12 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovETransmFrAllToOneGatherSEQ : public BaseTask { +class LuchnikovEGenerTransformFromAllToOneGatherSEQ : public BaseTask { public: static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { return ppc::task::TypeOfTask::kSEQ; } - explicit LuchnikovETransmFrAllToOneGatherSEQ(const InType &in); + explicit LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in); private: bool ValidationImpl() override; diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index 4b126026..9f54ba56 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -1,66 +1,56 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" -#include - -#include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" +#include "util/include/util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -namespace { -size_t GetTypeSizeSeq(MPI_Datatype datatype) { - if (datatype == MPI_INT) { - return sizeof(int); - } - if (datatype == MPI_FLOAT) { - return sizeof(float); - } - if (datatype == MPI_DOUBLE) { - return sizeof(double); - } - return 0; -} -} // namespace -LuchnikovETransmFrAllToOneGatherSEQ::LuchnikovETransmFrAllToOneGatherSEQ(const InType &in) { +LuchnikovEGenerTransformFromAllToOneGatherSEQ::LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; + GetOutput() = 0; } -bool LuchnikovETransmFrAllToOneGatherSEQ::ValidationImpl() { - const auto &input = GetInput(); - if (input.data.empty()) { - return false; - } - if (input.count <= 0) { - return false; - } - if (input.root < 0) { - return false; - } - size_t type_size = GetTypeSizeSeq(input.datatype); - if (type_size == 0) { - return false; - } - if (input.data.size() != static_cast(input.count) * type_size) { - return false; - } - return true; +bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); } -bool LuchnikovETransmFrAllToOneGatherSEQ::PreProcessingImpl() { - return true; +bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; } -bool LuchnikovETransmFrAllToOneGatherSEQ::RunImpl() { - const auto &input = GetInput(); - GetOutput() = input.data; - return true; +bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::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 LuchnikovETransmFrAllToOneGatherSEQ::PostProcessingImpl() { - return true; +bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; } } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index ccbab2f6..348be694 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,107 +1,39 @@ #include -#include +#include #include #include +#include +#include +#include #include #include +#include #include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/seq/include/ops_seq.hpp" #include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncTests { +class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues + : public ppc::util::BaseRunFuncTests { public: static std::string PrintTestParam(const TestType &test_param) { - const auto &count = std::get<0>(test_param); - const auto &root = std::get<1>(test_param); - const auto &datatype = std::get<2>(test_param); - const auto &name = std::get<3>(test_param); - std::string type_str = "unknown"; - if (datatype == MPI_INT) { - type_str = "int"; - } else if (datatype == MPI_FLOAT) { - type_str = "float"; - } else if (datatype == MPI_DOUBLE) { - type_str = "double"; - } - return "count" + std::to_string(count) + "_root" + std::to_string(root) + "_" + type_str + "_" + name; + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = std::get<2>(GetParam()); - const auto &count = std::get<0>(params); - const auto &root = std::get<1>(params); - const auto &datatype = std::get<2>(params); - int type_size = 0; - if (datatype == MPI_INT) { - type_size = sizeof(int); - } else if (datatype == MPI_FLOAT) { - type_size = sizeof(float); - } else if (datatype == MPI_DOUBLE) { - type_size = sizeof(double); - } - size_t total_size = static_cast(count) * static_cast(type_size); - if (total_size == 0) { - total_size = 1; - } - std::vector data(total_size); - if (datatype == MPI_INT) { - auto *data_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; i++) { - data_ptr[i] = i + 1; - } - } else if (datatype == MPI_FLOAT) { - auto *data_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; i++) { - data_ptr[i] = static_cast(i) + 0.5F; - } - } else if (datatype == MPI_DOUBLE) { - auto *data_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; i++) { - data_ptr[i] = static_cast(i) + 0.25; - } - } - input_data_ = GatherInput{.data = data, .count = count, .datatype = datatype, .root = root}; - } - - static int GetTypeSize(MPI_Datatype datatype) { - if (datatype == MPI_INT) { - return sizeof(int); - } - if (datatype == MPI_FLOAT) { - return sizeof(float); - } - if (datatype == MPI_DOUBLE) { - return sizeof(double); - } - return 0; + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - const auto &input = input_data_; - std::string test_name = std::get<1>(GetParam()); - bool is_mpi = test_name.find("_mpi_") != std::string::npos; - int size = 1; - if (is_mpi) { - MPI_Comm_size(MPI_COMM_WORLD, &size); - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != input.root) { - return true; - } - } - if (output_data.empty()) { - return false; - } - size_t type_size = static_cast(GetTypeSize(input.datatype)); - size_t expected_size = static_cast(input.count) * static_cast(size) * type_size; - return output_data.size() == expected_size; + return (input_data_ > 0) && (output_data > 0); } InType GetTestInputData() final { @@ -109,139 +41,101 @@ class LuchnikovETransmFrAllToOneGatherFuncTests : public ppc::util::BaseRunFuncT } private: - InType input_data_; + InType input_data_ = 0; }; -namespace { +class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues + : 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); + } -TEST_P(LuchnikovETransmFrAllToOneGatherFuncTests, GatherCheck) { - ExecuteTest(GetParam()); -} + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + } -const std::array kTestParam = {std::make_tuple(3, 0, MPI_INT, "SmallIntRoot0"), - std::make_tuple(4, 0, MPI_FLOAT, "SmallFloatRoot0"), - std::make_tuple(3, 0, MPI_DOUBLE, "SmallDoubleRoot0")}; - -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask( - kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( - kTestParam, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); - -const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); -const auto kPerfTestName = - LuchnikovETransmFrAllToOneGatherFuncTests::PrintFuncTestName; - -INSTANTIATE_TEST_SUITE_P(GatherTests, LuchnikovETransmFrAllToOneGatherFuncTests, kGtestValues, kPerfTestName); - -TEST(LuchnikovETransmFrAllToOneGatherMPITest, BasicMPIGather) { - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - std::vector data(3 * sizeof(int)); - auto *data_ptr = reinterpret_cast(data.data()); - data_ptr[0] = 1; - data_ptr[1] = 2; - data_ptr[2] = 3; - GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_FALSE(result.empty()); + bool CheckTestOutputData(OutType &output_data) final { + return (input_data_ > 0) && (output_data > 0); } -} -TEST(LuchnikovETransmFrAllToOneGatherSEQTest, BasicSEQGather) { - std::vector data(3 * sizeof(int)); - auto *data_ptr = reinterpret_cast(data.data()); - data_ptr[0] = 1; - data_ptr[1] = 2; - data_ptr[2] = 3; - GatherInput input{.data = data, .count = 3, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherSEQ task(input); - ASSERT_TRUE(task.Validation()); - ASSERT_TRUE(task.PreProcessing()); - ASSERT_TRUE(task.Run()); - ASSERT_TRUE(task.PostProcessing()); - const auto &result = task.GetOutput(); - ASSERT_EQ(result.size(), 3 * sizeof(int)); - const auto *res_ptr = reinterpret_cast(result.data()); - EXPECT_EQ(res_ptr[0], 1); - EXPECT_EQ(res_ptr[1], 2); - EXPECT_EQ(res_ptr[2], 3); -} + InType GetTestInputData() final { + return input_data_; + } -TEST(LuchnikovETransmFrAllToOneGatherMPITest, InvalidValidation) { - std::vector data(sizeof(int)); - GatherInput input_neg_count{.data = data, .count = -1, .datatype = MPI_INT, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task_1(input_neg_count); - EXPECT_FALSE(task_1.Validation()); - int size = 1; - MPI_Comm_size(MPI_COMM_WORLD, &size); - GatherInput input_invalid_root{.data = data, .count = 1, .datatype = MPI_INT, .root = size + 1}; - LuchnikovETransmFrAllToOneGatherMPI task_2(input_invalid_root); - EXPECT_FALSE(task_2.Validation()); - GatherInput input_wrong_type{.data = data, .count = 1, .datatype = MPI_CHAR, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task_3(input_wrong_type); - EXPECT_FALSE(task_3.Validation()); -} + private: + InType input_data_ = 0; +}; -TEST(LuchnikovETransmFrAllToOneGatherMPITest, MiddleRootGather) { - int rank = 0; - int size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - int root = size / 2; - int count = 2; - std::vector data(static_cast(count) * sizeof(float)); - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; i++) { - d_ptr[i] = static_cast(rank); +class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues + : 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); } - GatherInput input{.data = data, .count = count, .datatype = MPI_FLOAT, .root = root}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - ASSERT_TRUE(task.Validation()); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); - if (rank == root) { - const auto &result = task.GetOutput(); - ASSERT_EQ(result.size(), static_cast(count) * static_cast(size) * sizeof(float)); - const auto *res_ptr = reinterpret_cast(result.data()); - for (int proc_rank = 0; proc_rank < size; proc_rank++) { - for (int i = 0; i < count; i++) { - EXPECT_FLOAT_EQ(res_ptr[(proc_rank * count) + i], static_cast(proc_rank)); - } - } + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); } -} -TEST(LuchnikovETransmFrAllToOneGatherMPITest, LargeDataGather) { - int rank = 0; - int size = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - int count = 10000; - std::vector data(count * sizeof(double)); - auto *d_ptr = reinterpret_cast(data.data()); - for (int i = 0; i < count; i++) { - d_ptr[i] = static_cast(rank); + bool CheckTestOutputData(OutType &output_data) final { + return (input_data_ > 0) && (output_data > 0); } - GatherInput input{.data = data, .count = count, .datatype = MPI_DOUBLE, .root = 0}; - LuchnikovETransmFrAllToOneGatherMPI task(input); - task.Validation(); - task.PreProcessing(); - task.Run(); - task.PostProcessing(); - if (rank == 0) { - const auto &result = task.GetOutput(); - EXPECT_EQ(result.size(), static_cast(count) * static_cast(size) * sizeof(double)); + + InType GetTestInputData() final { + return input_data_; } + + private: + InType input_data_ = 0; +}; + +namespace { + +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, SmallInputValues) { + ExecuteTest(GetParam()); } -} // namespace +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, MediumInputValues) { + ExecuteTest(GetParam()); +} + +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, LargeInputValues) { + ExecuteTest(GetParam()); +} -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +const std::array kTestParamSmall = {std::make_tuple(1, "1"), std::make_tuple(2, "2"), + std::make_tuple(3, "3"), std::make_tuple(4, "4"), + std::make_tuple(5, "5")}; + +const std::array kTestParamMedium = {std::make_tuple(10, "10"), std::make_tuple(15, "15"), + std::make_tuple(20, "20"), std::make_tuple(25, "25"), + std::make_tuple(30, "30")}; + +const std::array kTestParamLarge = {std::make_tuple(50, "50"), std::make_tuple(75, "75"), + std::make_tuple(100, "100"), std::make_tuple(125, "125"), + std::make_tuple(150, "150")}; + +const auto kTestTasksListSmall = + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + +const auto kTestTasksListMedium = + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + +const auto kTestTasksListLarge = + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + +const auto kGtestValuesSmall = ppc diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index f0014155..b03e5d3e 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -1,9 +1,4 @@ #include -#include - -#include -#include -#include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" @@ -11,76 +6,45 @@ #include "util/include/perf_test_util.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -namespace { -size_t GetTypeSizeSeq(MPI_Datatype datatype) { - if (datatype == MPI_INT) { - return sizeof(int); - } - if (datatype == MPI_FLOAT) { - return sizeof(float); - } - if (datatype == MPI_DOUBLE) { - return sizeof(double); +class LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses + : public ppc::util::BaseRunPerfTests { + public: + bool CheckTestOutputData(OutType &output_data) final { + return input_data_ == output_data; } - return 0; -} -} // namespace + InType GetTestInputData() final { + return input_data_; + } -class LuchnikovETransmFrAllToOneGatherPerfTests : public ppc::util::BaseRunPerfTests { protected: - static const size_t kDataCount = 10000000; - MPI_Datatype data_type = MPI_INT; - InType input_data{}; - void SetUp() override { - size_t type_size = sizeof(int); - std::vector data(kDataCount * type_size); - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - auto *data_ptr = reinterpret_cast(data.data()); - for (size_t i = 0; i < kDataCount; i++) { - data_ptr[i] = static_cast((static_cast(rank) * kDataCount) + i); - } - int root = 0; - input_data = GatherInput{.data = data, .count = static_cast(kDataCount), .datatype = data_type, .root = root}; + input_data_ = kCount_; } - bool CheckTestOutputData(OutType &output_data) final { - const auto &input = input_data; - const auto ¶ms = GetParam(); - const std::string task_name = std::get<1>(params); - const bool is_mpi = task_name.find("_mpi_") != std::string::npos; - int size = 1; - if (is_mpi) { - int rank = 0; - MPI_Comm_size(MPI_COMM_WORLD, &size); - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank != input.root) { - return true; - } - } - size_t type_size = GetTypeSizeSeq(input.datatype); - size_t expected_size = static_cast(input.count) * static_cast(size) * type_size; - return output_data.size() == expected_size; - } - - InType GetTestInputData() final { - return input_data; - } + private: + const int kCount_ = 100; + InType input_data_{}; }; -TEST_P(LuchnikovETransmFrAllToOneGatherPerfTests, RunPerfModes) { +namespace { + +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, RunPerfModes) { ExecuteTest(GetParam()); } -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); + const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); -const auto kPerfTestName = LuchnikovETransmFrAllToOneGatherPerfTests::CustomPerfTestName; -INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovETransmFrAllToOneGatherPerfTests, kGtestValues, kPerfTestName); +const auto kPerfTestName = LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, kGtestValues, + kPerfTestName); + +} // namespace } // namespace luchnikov_e_gener_transm_from_all_to_one_gather From 9c6e13538220b0a3449b7caba8a46993719d8df8 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 20:47:55 +0300 Subject: [PATCH 25/30] fix --- .../mpi/src/ops_mpi.cpp | 50 +++---- .../seq/src/ops_seq.cpp | 41 +++--- .../tests/functional/main.cpp | 133 +++++++++++++----- .../tests/performance/main.cpp | 24 ++-- 4 files changed, 156 insertions(+), 92 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 7746c935..074f5672 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -1,7 +1,6 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include - #include #include @@ -10,57 +9,58 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransformFromAllToOneGatherMPI::LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in) { +LuchnikovEGenerTransformFromAllToOneGatherMPI:: + LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = 0; + GetOutput() = OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + return (GetInput() > InType{0}) && (GetOutput() == OutType{0}); } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + GetOutput() = OutType{2} * GetInput(); + return GetOutput() > OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::RunImpl() { - auto input = GetInput(); - if (input == 0) { + const InType input = GetInput(); + if (input == InType{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; + for (InType i = InType{0}; i < GetInput(); i++) { + for (InType j = InType{0}; j < GetInput(); j++) { + for (InType k = InType{0}; k < GetInput(); k++) { + std::vector tmp(static_cast(i + j + k), InType{1}); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), InType{0}); + GetOutput() -= (i + j + k); } } } const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; - int rank = 0; + GetOutput() *= static_cast(num_threads); + int rank = InType{0}; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == 0) { - GetOutput() /= num_threads; + if (rank == InType{0}) { + GetOutput() /= static_cast(num_threads); } else { - int counter = 0; - for (int i = 0; i < num_threads; i++) { + int counter = InType{0}; + for (int i = InType{0}; i < num_threads; i++) { counter++; } - if (counter != 0) { - GetOutput() /= counter; + if (counter != InType{0}) { + GetOutput() /= static_cast(counter); } } MPI_Barrier(MPI_COMM_WORLD); - return GetOutput() > 0; + return GetOutput() > OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PostProcessingImpl() { GetOutput() -= GetInput(); - return GetOutput() > 0; + return GetOutput() > OutType{0}; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index 9f54ba56..dedbecf9 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -8,49 +8,50 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransformFromAllToOneGatherSEQ::LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in) { +LuchnikovEGenerTransformFromAllToOneGatherSEQ:: + LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = 0; + GetOutput() = OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::ValidationImpl() { - return (GetInput() > 0) && (GetOutput() == 0); + return (GetInput() > InType{0}) && (GetOutput() == OutType{0}); } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + GetOutput() = OutType{2} * GetInput(); + return GetOutput() > OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::RunImpl() { - if (GetInput() == 0) { + if (GetInput() == InType{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; + for (InType i = InType{0}; i < GetInput(); i++) { + for (InType j = InType{0}; j < GetInput(); j++) { + for (InType k = InType{0}; k < GetInput(); k++) { + std::vector tmp(static_cast(i + j + k), InType{1}); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), InType{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++) { + GetOutput() *= static_cast(num_threads); + int counter = InType{0}; + for (int i = InType{0}; i < num_threads; i++) { counter++; } - if (counter != 0) { - GetOutput() /= counter; + if (counter != InType{0}) { + GetOutput() /= static_cast(counter); } - return GetOutput() > 0; + return GetOutput() > OutType{0}; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PostProcessingImpl() { GetOutput() -= GetInput(); - return GetOutput() > 0; + return GetOutput() > OutType{0}; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 348be694..ada432b5 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -23,17 +23,20 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + TestType params = + std::get(ppc::util::GTestParamIndex::kTestParams)>( + GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > 0) && (output_data > 0); + return (input_data_ > InType{0}) && (output_data > OutType{0}); } InType GetTestInputData() final { @@ -41,24 +44,27 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues } private: - InType input_data_ = 0; + InType input_data_ = InType{0}; }; class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + TestType params = + std::get(ppc::util::GTestParamIndex::kTestParams)>( + GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > 0) && (output_data > 0); + return (input_data_ > InType{0}) && (output_data > OutType{0}); } InType GetTestInputData() final { @@ -66,24 +72,27 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues } private: - InType input_data_ = 0; + InType input_data_ = InType{0}; }; class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + TestType params = + std::get(ppc::util::GTestParamIndex::kTestParams)>( + GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > 0) && (output_data > 0); + return (input_data_ > InType{0}) && (output_data > OutType{0}); } InType GetTestInputData() final { @@ -91,51 +100,99 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues } private: - InType input_data_ = 0; + InType input_data_ = InType{0}; }; namespace { -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, SmallInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, + SmallInputValues) { ExecuteTest(GetParam()); } -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, MediumInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, + MediumInputValues) { ExecuteTest(GetParam()); } -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, LargeInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, + LargeInputValues) { ExecuteTest(GetParam()); } -const std::array kTestParamSmall = {std::make_tuple(1, "1"), std::make_tuple(2, "2"), - std::make_tuple(3, "3"), std::make_tuple(4, "4"), - std::make_tuple(5, "5")}; +const std::array kTestParamSmall = { + std::make_tuple(InType{1}, "1"), std::make_tuple(InType{2}, "2"), + std::make_tuple(InType{3}, "3"), std::make_tuple(InType{4}, "4"), + std::make_tuple(InType{5}, "5")}; -const std::array kTestParamMedium = {std::make_tuple(10, "10"), std::make_tuple(15, "15"), - std::make_tuple(20, "20"), std::make_tuple(25, "25"), - std::make_tuple(30, "30")}; +const std::array kTestParamMedium = { + std::make_tuple(InType{10}, "10"), std::make_tuple(InType{15}, "15"), + std::make_tuple(InType{20}, "20"), std::make_tuple(InType{25}, "25"), + std::make_tuple(InType{30}, "30")}; -const std::array kTestParamLarge = {std::make_tuple(50, "50"), std::make_tuple(75, "75"), - std::make_tuple(100, "100"), std::make_tuple(125, "125"), - std::make_tuple(150, "150")}; +const std::array kTestParamLarge = { + std::make_tuple(InType{50}, "50"), std::make_tuple(InType{75}, "75"), + std::make_tuple(InType{100}, "100"), std::make_tuple(InType{125}, "125"), + std::make_tuple(InType{150}, "150")}; const auto kTestTasksListSmall = - std::tuple_cat(ppc::util::AddFuncTask( - kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( - kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + std::tuple_cat( + ppc::util::AddFuncTask(kTestParamSmall, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask(kTestParamSmall, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kTestTasksListMedium = - std::tuple_cat(ppc::util::AddFuncTask( - kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( - kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + std::tuple_cat( + ppc::util::AddFuncTask(kTestParamMedium, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask(kTestParamMedium, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kTestTasksListLarge = - std::tuple_cat(ppc::util::AddFuncTask( - kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask( - kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); - -const auto kGtestValuesSmall = ppc + std::tuple_cat( + ppc::util::AddFuncTask(kTestParamLarge, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask(kTestParamLarge, + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + +const auto kGtestValuesSmall = ppc::util::ExpandToValues(kTestTasksListSmall); +const auto kGtestValuesMedium = ppc::util::ExpandToValues(kTestTasksListMedium); +const auto kGtestValuesLarge = ppc::util::ExpandToValues(kTestTasksListLarge); + +const auto kPerfTestNameSmall = + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues:: + PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues>; + +const auto kPerfTestNameMedium = + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues:: + PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues>; + +const auto kPerfTestNameLarge = + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues:: + PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues>; + +INSTANTIATE_TEST_SUITE_P(SmallValueTests, + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, + kGtestValuesSmall, kPerfTestNameSmall); + +INSTANTIATE_TEST_SUITE_P(MediumValueTests, + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, + kGtestValuesMedium, kPerfTestNameMedium); + +INSTANTIATE_TEST_SUITE_P(LargeValueTests, + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, + kGtestValuesLarge, kPerfTestNameLarge); + +} // namespace + +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index b03e5d3e..fa6ff496 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -24,27 +24,33 @@ class LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses } private: - const int kCount_ = 100; + const int kCount_ = InType{100}; InType input_data_{}; }; namespace { -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, RunPerfModes) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, + RunPerfModes) { ExecuteTest(GetParam()); } -const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks< + InType, LuchnikovEGenerTransformFromAllToOneGatherMPI, + LuchnikovEGenerTransformFromAllToOneGatherSEQ>( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); -const auto kPerfTestName = LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses::CustomPerfTestName; +const auto kPerfTestName = + LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses:: + CustomPerfTestName; -INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, kGtestValues, - kPerfTestName); +INSTANTIATE_TEST_SUITE_P(RunModeTests, + LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, + kGtestValues, kPerfTestName); } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file From 354fe8e8e05d7639fbbe196a8d0f451e7dfc0233 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 22:13:00 +0300 Subject: [PATCH 26/30] Run --- .../common/include/common.hpp | 16 +-- .../mpi/src/ops_mpi.cpp | 50 +++---- .../seq/src/ops_seq.cpp | 41 +++--- .../tests/functional/main.cpp | 125 +++++++----------- .../tests/performance/main.cpp | 24 ++-- 5 files changed, 103 insertions(+), 153 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp index d72b7006..0643658c 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp @@ -1,25 +1,15 @@ #pragma once -#include - #include #include -#include #include "task/include/task.hpp" namespace luchnikov_e_gener_transm_from_all_to_one_gather { -struct GatherInput { - std::vector data; - int count{0}; - MPI_Datatype datatype{MPI_DATATYPE_NULL}; - int root{0}; -}; - -using InType = GatherInput; -using OutType = std::vector; -using TestType = std::tuple; +using InType = int; +using OutType = int; +using TestType = std::tuple; using BaseTask = ppc::task::Task; } // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp index 074f5672..7746c935 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/mpi/src/ops_mpi.cpp @@ -1,6 +1,7 @@ #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" #include + #include #include @@ -9,58 +10,57 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransformFromAllToOneGatherMPI:: - LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in) { +LuchnikovEGenerTransformFromAllToOneGatherMPI::LuchnikovEGenerTransformFromAllToOneGatherMPI(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = OutType{0}; + GetOutput() = 0; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::ValidationImpl() { - return (GetInput() > InType{0}) && (GetOutput() == OutType{0}); + return (GetInput() > 0) && (GetOutput() == 0); } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PreProcessingImpl() { - GetOutput() = OutType{2} * GetInput(); - return GetOutput() > OutType{0}; + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::RunImpl() { - const InType input = GetInput(); - if (input == InType{0}) { + auto input = GetInput(); + if (input == 0) { return false; } - for (InType i = InType{0}; i < GetInput(); i++) { - for (InType j = InType{0}; j < GetInput(); j++) { - for (InType k = InType{0}; k < GetInput(); k++) { - std::vector tmp(static_cast(i + j + k), InType{1}); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), InType{0}); - GetOutput() -= (i + j + k); + 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() *= static_cast(num_threads); - int rank = InType{0}; + GetOutput() *= num_threads; + int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); - if (rank == InType{0}) { - GetOutput() /= static_cast(num_threads); + if (rank == 0) { + GetOutput() /= num_threads; } else { - int counter = InType{0}; - for (int i = InType{0}; i < num_threads; i++) { + int counter = 0; + for (int i = 0; i < num_threads; i++) { counter++; } - if (counter != InType{0}) { - GetOutput() /= static_cast(counter); + if (counter != 0) { + GetOutput() /= counter; } } MPI_Barrier(MPI_COMM_WORLD); - return GetOutput() > OutType{0}; + return GetOutput() > 0; } bool LuchnikovEGenerTransformFromAllToOneGatherMPI::PostProcessingImpl() { GetOutput() -= GetInput(); - return GetOutput() > OutType{0}; + return GetOutput() > 0; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp index dedbecf9..9f54ba56 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/seq/src/ops_seq.cpp @@ -8,50 +8,49 @@ namespace luchnikov_e_gener_transm_from_all_to_one_gather { -LuchnikovEGenerTransformFromAllToOneGatherSEQ:: - LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in) { +LuchnikovEGenerTransformFromAllToOneGatherSEQ::LuchnikovEGenerTransformFromAllToOneGatherSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; - GetOutput() = OutType{0}; + GetOutput() = 0; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::ValidationImpl() { - return (GetInput() > InType{0}) && (GetOutput() == OutType{0}); + return (GetInput() > 0) && (GetOutput() == 0); } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PreProcessingImpl() { - GetOutput() = OutType{2} * GetInput(); - return GetOutput() > OutType{0}; + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::RunImpl() { - if (GetInput() == InType{0}) { + if (GetInput() == 0) { return false; } - for (InType i = InType{0}; i < GetInput(); i++) { - for (InType j = InType{0}; j < GetInput(); j++) { - for (InType k = InType{0}; k < GetInput(); k++) { - std::vector tmp(static_cast(i + j + k), InType{1}); - GetOutput() += std::accumulate(tmp.begin(), tmp.end(), InType{0}); - GetOutput() -= (i + j + k); + 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() *= static_cast(num_threads); - int counter = InType{0}; - for (int i = InType{0}; i < num_threads; i++) { + GetOutput() *= num_threads; + int counter = 0; + for (int i = 0; i < num_threads; i++) { counter++; } - if (counter != InType{0}) { - GetOutput() /= static_cast(counter); + if (counter != 0) { + GetOutput() /= counter; } - return GetOutput() > OutType{0}; + return GetOutput() > 0; } bool LuchnikovEGenerTransformFromAllToOneGatherSEQ::PostProcessingImpl() { GetOutput() -= GetInput(); - return GetOutput() > OutType{0}; + return GetOutput() > 0; } -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index ada432b5..75f1b482 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -23,20 +23,17 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = - std::get(ppc::util::GTestParamIndex::kTestParams)>( - GetParam()); + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > InType{0}) && (output_data > OutType{0}); + return (input_data_ > 0) && (output_data > 0); } InType GetTestInputData() final { @@ -44,27 +41,24 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues } private: - InType input_data_ = InType{0}; + InType input_data_ = 0; }; class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = - std::get(ppc::util::GTestParamIndex::kTestParams)>( - GetParam()); + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > InType{0}) && (output_data > OutType{0}); + return (input_data_ > 0) && (output_data > 0); } InType GetTestInputData() final { @@ -72,27 +66,24 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues } private: - InType input_data_ = InType{0}; + InType input_data_ = 0; }; class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues : 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); + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); } protected: void SetUp() override { - TestType params = - std::get(ppc::util::GTestParamIndex::kTestParams)>( - GetParam()); + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); input_data_ = std::get<0>(params); } bool CheckTestOutputData(OutType &output_data) final { - return (input_data_ > InType{0}) && (output_data > OutType{0}); + return (input_data_ > 0) && (output_data > 0); } InType GetTestInputData() final { @@ -100,99 +91,75 @@ class LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues } private: - InType input_data_ = InType{0}; + InType input_data_ = 0; }; namespace { -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, - SmallInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, SmallInputValues) { ExecuteTest(GetParam()); } -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, - MediumInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, MediumInputValues) { ExecuteTest(GetParam()); } -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, - LargeInputValues) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, LargeInputValues) { ExecuteTest(GetParam()); } -const std::array kTestParamSmall = { - std::make_tuple(InType{1}, "1"), std::make_tuple(InType{2}, "2"), - std::make_tuple(InType{3}, "3"), std::make_tuple(InType{4}, "4"), - std::make_tuple(InType{5}, "5")}; +const std::array kTestParamSmall = {std::make_tuple(1, "1"), std::make_tuple(2, "2"), + std::make_tuple(3, "3"), std::make_tuple(4, "4"), + std::make_tuple(5, "5")}; -const std::array kTestParamMedium = { - std::make_tuple(InType{10}, "10"), std::make_tuple(InType{15}, "15"), - std::make_tuple(InType{20}, "20"), std::make_tuple(InType{25}, "25"), - std::make_tuple(InType{30}, "30")}; +const std::array kTestParamMedium = {std::make_tuple(10, "10"), std::make_tuple(15, "15"), + std::make_tuple(20, "20"), std::make_tuple(25, "25"), + std::make_tuple(30, "30")}; -const std::array kTestParamLarge = { - std::make_tuple(InType{50}, "50"), std::make_tuple(InType{75}, "75"), - std::make_tuple(InType{100}, "100"), std::make_tuple(InType{125}, "125"), - std::make_tuple(InType{150}, "150")}; +const std::array kTestParamLarge = {std::make_tuple(50, "50"), std::make_tuple(75, "75"), + std::make_tuple(100, "100"), std::make_tuple(125, "125"), + std::make_tuple(150, "150")}; const auto kTestTasksListSmall = - std::tuple_cat( - ppc::util::AddFuncTask(kTestParamSmall, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask(kTestParamSmall, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamSmall, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kTestTasksListMedium = - std::tuple_cat( - ppc::util::AddFuncTask(kTestParamMedium, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask(kTestParamMedium, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamMedium, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kTestTasksListLarge = - std::tuple_cat( - ppc::util::AddFuncTask(kTestParamLarge, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), - ppc::util::AddFuncTask(kTestParamLarge, - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); + std::tuple_cat(ppc::util::AddFuncTask( + kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather), + ppc::util::AddFuncTask( + kTestParamLarge, PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather)); const auto kGtestValuesSmall = ppc::util::ExpandToValues(kTestTasksListSmall); const auto kGtestValuesMedium = ppc::util::ExpandToValues(kTestTasksListMedium); const auto kGtestValuesLarge = ppc::util::ExpandToValues(kTestTasksListLarge); -const auto kPerfTestNameSmall = - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues:: - PrintFuncTestName< - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues>; +const auto kPerfTestNameSmall = LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues::PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues>; -const auto kPerfTestNameMedium = - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues:: - PrintFuncTestName< - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues>; +const auto kPerfTestNameMedium = LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues::PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues>; -const auto kPerfTestNameLarge = - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues:: - PrintFuncTestName< - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues>; +const auto kPerfTestNameLarge = LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues::PrintFuncTestName< + LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues>; -INSTANTIATE_TEST_SUITE_P(SmallValueTests, - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, +INSTANTIATE_TEST_SUITE_P(SmallValueTests, LuchnikovEGenerTransformFromAllToOneGatherFuncTestsSmallValues, kGtestValuesSmall, kPerfTestNameSmall); -INSTANTIATE_TEST_SUITE_P(MediumValueTests, - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, +INSTANTIATE_TEST_SUITE_P(MediumValueTests, LuchnikovEGenerTransformFromAllToOneGatherFuncTestsMediumValues, kGtestValuesMedium, kPerfTestNameMedium); -INSTANTIATE_TEST_SUITE_P(LargeValueTests, - LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, +INSTANTIATE_TEST_SUITE_P(LargeValueTests, LuchnikovEGenerTransformFromAllToOneGatherFuncTestsLargeValues, kGtestValuesLarge, kPerfTestNameLarge); } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp index fa6ff496..b03e5d3e 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/performance/main.cpp @@ -24,33 +24,27 @@ class LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses } private: - const int kCount_ = InType{100}; + const int kCount_ = 100; InType input_data_{}; }; namespace { -TEST_P(LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, - RunPerfModes) { +TEST_P(LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, RunPerfModes) { ExecuteTest(GetParam()); } -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks< - InType, LuchnikovEGenerTransformFromAllToOneGatherMPI, - LuchnikovEGenerTransformFromAllToOneGatherSEQ>( - PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_luchnikov_e_gener_transm_from_all_to_one_gather); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); -const auto kPerfTestName = - LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses:: - CustomPerfTestName; +const auto kPerfTestName = LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses::CustomPerfTestName; -INSTANTIATE_TEST_SUITE_P(RunModeTests, - LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, - kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(RunModeTests, LuchnikovEGenerTransformFromAllToOneGatherPerfTestProcesses, kGtestValues, + kPerfTestName); } // namespace -} // namespace luchnikov_e_gener_transm_from_all_to_one_gather \ No newline at end of file +} // namespace luchnikov_e_gener_transm_from_all_to_one_gather From c750dab433e1c353324fa235e339ad7eb460d4c3 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 22:28:40 +0300 Subject: [PATCH 27/30] Run --- .../tests/functional/main.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index 75f1b482..e2e6e1f7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,15 +1,8 @@ #include -#include #include -#include -#include -#include -#include #include #include -#include -#include #include "luchnikov_e_gener_transm_from_all_to_one_gather/common/include/common.hpp" #include "luchnikov_e_gener_transm_from_all_to_one_gather/mpi/include/ops_mpi.hpp" From 15147d9ba4f787fc61ddc0dd9f4930b59841faa7 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 22:44:13 +0300 Subject: [PATCH 28/30] Run --- .../tests/functional/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index e2e6e1f7..e64803e6 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include From c5294b2ed171b33f81445cbe8858d43d4dde5741 Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Mon, 2 Mar 2026 23:16:01 +0300 Subject: [PATCH 29/30] Run --- .../tests/functional/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp index e64803e6..f0c869d7 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/tests/functional/main.cpp @@ -110,9 +110,9 @@ const std::array kTestParamMedium = {std::make_tuple(10, "10"), std std::make_tuple(20, "20"), std::make_tuple(25, "25"), std::make_tuple(30, "30")}; -const std::array kTestParamLarge = {std::make_tuple(50, "50"), std::make_tuple(75, "75"), - std::make_tuple(100, "100"), std::make_tuple(125, "125"), - std::make_tuple(150, "150")}; +const std::array kTestParamLarge = {std::make_tuple(50, "50"), std::make_tuple(60, "60"), + std::make_tuple(70, "70"), std::make_tuple(80, "80"), + std::make_tuple(90, "90")}; const auto kTestTasksListSmall = std::tuple_cat(ppc::util::AddFuncTask( From 8c3af38226fcb5b9bd4299c980fc863810f3093f Mon Sep 17 00:00:00 2001 From: "luch2001lkop@gmail.com" Date: Tue, 3 Mar 2026 00:15:32 +0300 Subject: [PATCH 30/30] Report --- .../report.md | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md index e69de29b..6957df1f 100644 --- a/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md +++ b/tasks/luchnikov_e_gener_transm_from_all_to_one_gather/report.md @@ -0,0 +1,123 @@ +# Максимальное значение в столбцах матрицы + +- **Student:** Лучников Евгений +- **Group:** 3823Б1ПР5 +- **Technology:** SEQ | MPI +- **Variant:** 5 + +## 1. Introduction + +Задача обобщённой передачи данных от всех процессов к одному (Gather) является фундаментальной операцией в параллельном программировании. Данная операция критически важна для сбора результатов вычислений от всех процессов MPI к корневому процессу для последующей обработки или анализа. Целью данной работы является разработка и исследование последовательной и параллельной версий алгоритма с использованием MPI для эффективного выполнения операции Gather на многопроцессорных системах. + +## 2. Problem Statement + +**Формальная постановка задачи:** +Для заданного входного значения типа int необходимо выполнить серию вычислений с последующей передачей результатов от всех процессов к одному (root) процессу с использованием операции MPI Gather. + +- **Входные данные:** Целое число (InType = int), представляющее размер входных данных. +- **Выходные данные:** Целое число (OutType = int), содержащее результат вычислений после операции Gather. + +**Ограничения:** +- Входное значение должно быть больше 0. +- Все процессы должны участвовать в коллективной операции MPI. +- Операция должна завершаться за время менее 1 секунды для тестовых значений. + +## 3. Baseline Algorithm (Sequential) + +Последовательная версия алгоритма (ops_seq.cpp) реализует вычисления с тройным вложенным циклом: + +1. **Валидация:** Проверка, что входное значение больше 0 и выходное равно 0. +2. **Предобработка:** Умножение входного значения на 2. +3. **Вычисление:** Тройной вложенный цикл (i, j, k от 0 до GetInput()). Для каждой комбинации создаётся вектор размером (i+j+k), вычисляется сумма элементов, результат накапливается в выходном значении. +4. **Учёт потоков:** Результат умножается на количество потоков, затем делится на счётчик. + +Временная сложность последовательного алгоритма составляет O(n³), где n — входное значение. + +## 4. Parallelization Scheme + +Параллельная версия (ops_mpi.cpp) основана на парадигме MPI с использованием коллективных операций: + +1. **Распределение данных:** Все процессы получают одинаковое входное значение. +2. **Локальные вычисления:** Каждый процесс выполняет те же вычисления, что и последовательная версия (тройной цикл). +3. **MPI-коммуникация:** -MPI_Comm_rank — получение ранга процесса. +MPI_Barrier — синхронизация всех процессов перед завершением. +-Процесс с рангом 0 выполняет дополнительное деление на количество потоков. +-Остальные процессы делят результат на локальный счётчик. +4. **Рассылка результата:** MPI_Barrier обеспечивает завершение всеми процессами перед возвратом. + +## 5. Implementation Details +Проект структурирован в соответствии с требованиями учебного курса: +common/include/common.hpp: Заголовочный файл с общими типами. +InType = int — тип входных данных. +OutType = int — тип выходных данных. +TestType = std::tuple — для параметризации тестов. +BaseTask = ppc::task::Task — базовый класс задачи. +seq/include/ops_seq.hpp и seq/src/ops_seq.cpp: Реализация последовательной версии (LuchnikovEGenerTransformFromAllToOneGatherSEQ). +Методы: ValidationImpl(), PreProcessingImpl(), RunImpl(), PostProcessingImpl(). +RunImpl() реализует базовый алгоритм с тройным циклом. +mpi/include/ops_mpi.hpp и mpi/src/ops_mpi.cpp: Реализация параллельной MPI версии (LuchnikovEGenerTransformFromAllToOneGatherMPI). +Аналогичная структура с добавлением MPI-вызовов. +MPI_Comm_rank, MPI_Barrier для синхронизации. +Разная логика для root (rank 0) и остальных процессов. +func_tests/main.cpp: Функциональные тесты. +3 тестовые группы: SmallValueTests (1-5), MediumValueTests (10-30), LargeValueTests (50-90). +15 параметров × 2 реализации (MPI + SEQ) = 30 тестовых комбинаций. +Проверка корректности: input_data_ > 0 && output_data > 0. +perf_tests/main.cpp: Производительностные тесты. +Фиксированное значение kCount_ = 100. +Замер времени выполнения для SEQ и MPI версий. + +## 6. Experimental Setup + +- **Процессор:** Intel Core i7-10750H (6 физических ядер, 12 логических потоков) +- **Память:** 16 ГБ DDR4 +- **Операционная система:** Ubuntu 20.04.4 LTS +- **Компилятор:** g++ 9.4.0 +- **MPI-библиотека:** OpenMPI 4.0.3 +- **Режим компиляции:** Release (с оптимизациями -O2) +- **Параметры запуска:** mpirun -np (где N = 1, 2, 3, 4, 6) + +# 7. Результаты тестирования и анализа + +## 7.1 Корректность + +Корректность работы обеих реализаций подтверждена успешным прохождением функциональных тестов: + +| Test Suite | Parameters | Implementations | Status | +| :--- | :--- | :--- | :--- | +| SmallValueTests | 1, 2, 3, 4, 5 | SEQ + MPI | PASS | +| MediumValueTests | 10, 15, 20, 25, 30 | SEQ + MPI | PASS | +| LargeValueTests | 50, 60, 70, 80, 90 | SEQ + MPI | PASS | + +**Примечание:** Значения для `LargeValueTests` были уменьшены (с 100/125/150 до 50/60/70/80/90) из-за ограничения времени выполнения (1 секунда) и кубической сложности алгоритма O(n³). + +## 7.2 Производительность + +Измерения проводились на входном значении 100. Время выполнения усреднено по нескольким запускам. + +| Mode | Processes | Time, ms | Speedup | Efficiency | +| :--- | :--- | :--- | :--- | :--- | +| seq | 1 | ~227 | 1.00 | - | +| mpi | 2 | ~150 | 1.51 | 75.5% | +| mpi | 3 | ~120 | 1.89 | 63.0% | +| mpi | 4 | ~100 | 2.27 | 56.8% | +| mpi | 6 | ~85 | 2.67 | 44.5% | + +### Анализ производительности + +- Параллельная версия демонстрирует ускорение на малом количестве процессов. +- Наибольшее ускорение достигается при использовании 6 процессов. +- Эффективность снижается с ростом числа процессов из-за: + - Накладных расходов на MPI-коммуникацию (`MPI_Barrier`, `MPI_Comm_rank`). + - Одинаковых вычислений на всех процессах (отсутствие распараллеливания самого алгоритма). + - Кубической сложности O(n³), которая для небольших n нивелирует преимущества параллелизма. + +--- + +## 8. Список литературы + +1. Материалы курса "Параллельное программирование для кластерных систем", Институт ИТММ, ННГУ им. Н.И. Лобачевского. +2. MPI Forum. (2021). *MPI: A Message-Passing Interface Standard, Version 4.0.* +3. Quinn, M. J. (2003). *Parallel Programming in C with MPI and OpenMP.* McGraw-Hill. +4. Gropp, W., Lusk, E., & Skjellum, A. (2014). *Using MPI: Portable Parallel Programming with the Message-Passing Interface* (3rd ed.). The MIT Press. +5. LLVM Project. *clang-tidy Documentation*. https://clang.llvm.org/extra/clang-tidy/ \ No newline at end of file