From ba86ba870ad4db9a528af8f447eed91c4e64da5f Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Mon, 17 Nov 2025 17:50:15 +0300 Subject: [PATCH 01/16] Added a folder for 1 task --- .../common/include/common.hpp | 15 +++ .../data/pic.jpg | Bin 0 -> 23 bytes tasks/telnov_counting_the_frequency/info.json | 9 ++ .../mpi/include/ops_mpi.hpp | 22 +++++ .../mpi/src/ops_mpi.cpp | 72 +++++++++++++++ tasks/telnov_counting_the_frequency/report.md | 1 + .../seq/include/ops_seq.hpp | 22 +++++ .../seq/src/ops_seq.cpp | 60 ++++++++++++ .../settings.json | 7 ++ .../tests/.clang-tidy | 13 +++ .../tests/functional/main.cpp | 86 ++++++++++++++++++ .../tests/performance/main.cpp | 40 ++++++++ 12 files changed, 347 insertions(+) create mode 100644 tasks/telnov_counting_the_frequency/common/include/common.hpp create mode 100644 tasks/telnov_counting_the_frequency/data/pic.jpg create mode 100644 tasks/telnov_counting_the_frequency/info.json create mode 100644 tasks/telnov_counting_the_frequency/mpi/include/ops_mpi.hpp create mode 100644 tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp create mode 100644 tasks/telnov_counting_the_frequency/report.md create mode 100644 tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp create mode 100644 tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp create mode 100644 tasks/telnov_counting_the_frequency/settings.json create mode 100644 tasks/telnov_counting_the_frequency/tests/.clang-tidy create mode 100644 tasks/telnov_counting_the_frequency/tests/functional/main.cpp create mode 100644 tasks/telnov_counting_the_frequency/tests/performance/main.cpp diff --git a/tasks/telnov_counting_the_frequency/common/include/common.hpp b/tasks/telnov_counting_the_frequency/common/include/common.hpp new file mode 100644 index 0000000000..4025e60716 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace telnov_counting_the_frequency { + +using InType = int; +using OutType = int; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/data/pic.jpg b/tasks/telnov_counting_the_frequency/data/pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..637624238c89d914613ed301968bffbf462bc110 GIT binary patch literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY + +#include +#include + +#include "telnov_counting_the_frequency/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace telnov_counting_the_frequency { + +TelnovCountingTheFrequencyMPI::TelnovCountingTheFrequencyMPI(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool TelnovCountingTheFrequencyMPI::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool TelnovCountingTheFrequencyMPI::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool TelnovCountingTheFrequencyMPI::RunImpl() { + auto input = GetInput(); + if (input == 0) { + return false; + } + + for (InType i = 0; i < GetInput(); i++) { + for (InType j = 0; j < GetInput(); j++) { + for (InType k = 0; k < GetInput(); k++) { + std::vector tmp(i + j + k, 1); + GetOutput() += std::accumulate(tmp.begin(), tmp.end(), 0); + GetOutput() -= i + j + k; + } + } + } + + const int num_threads = ppc::util::GetNumThreads(); + GetOutput() *= num_threads; + + int rank = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) { + GetOutput() /= num_threads; + } else { + int counter = 0; + for (int i = 0; i < num_threads; i++) { + counter++; + } + + if (counter != 0) { + GetOutput() /= counter; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + return GetOutput() > 0; +} + +bool TelnovCountingTheFrequencyMPI::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/report.md b/tasks/telnov_counting_the_frequency/report.md new file mode 100644 index 0000000000..05f652b495 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/report.md @@ -0,0 +1 @@ +# Отчёт \ No newline at end of file diff --git a/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp b/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..cfb6886b7f --- /dev/null +++ b/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "telnov_counting_the_frequency/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace telnov_counting_the_frequency { + +class TelnovCountingTheFrequencySEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit TelnovCountingTheFrequencySEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..0bca090804 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -0,0 +1,60 @@ +#include "telnov_counting_the_frequency/seq/include/ops_seq.hpp" + +#include +#include + +#include "telnov_counting_the_frequency/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace telnov_counting_the_frequency { + +TelnovCountingTheFrequencySEQ::TelnovCountingTheFrequencySEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool TelnovCountingTheFrequencySEQ::ValidationImpl() { + return (GetInput() > 0) && (GetOutput() == 0); +} + +bool TelnovCountingTheFrequencySEQ::PreProcessingImpl() { + GetOutput() = 2 * GetInput(); + return GetOutput() > 0; +} + +bool TelnovCountingTheFrequencySEQ::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 TelnovCountingTheFrequencySEQ::PostProcessingImpl() { + GetOutput() -= GetInput(); + return GetOutput() > 0; +} + +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/settings.json b/tasks/telnov_counting_the_frequency/settings.json new file mode 100644 index 0000000000..b1a0d52574 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/telnov_counting_the_frequency/tests/.clang-tidy b/tasks/telnov_counting_the_frequency/tests/.clang-tidy new file mode 100644 index 0000000000..ef43b7aa8a --- /dev/null +++ b/tasks/telnov_counting_the_frequency/tests/.clang-tidy @@ -0,0 +1,13 @@ +InheritParentConfig: true + +Checks: > + -modernize-loop-convert, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-avoid-non-const-global-variables, + -misc-use-anonymous-namespace, + -modernize-use-std-print, + -modernize-type-traits + +CheckOptions: + - key: readability-function-cognitive-complexity.Threshold + value: 50 # Relaxed for tests diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp new file mode 100644 index 0000000000..a022a35be1 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -0,0 +1,86 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "telnov_counting_the_frequency/common/include/common.hpp" +#include "telnov_counting_the_frequency/mpi/include/ops_mpi.hpp" +#include "telnov_counting_the_frequency/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace telnov_counting_the_frequency { + +class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param); + } + + protected: + void SetUp() override { + int width = -1; + int height = -1; + int channels = -1; + std::vector img; + // Read image in RGB to ensure consistent channel count + { + std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); + auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); + if (data == nullptr) { + throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + } + channels = STBI_rgb; + img = std::vector(data, data + (static_cast(width * height * channels))); + stbi_image_free(data); + if (std::cmp_not_equal(width, height)) { + throw std::runtime_error("width != height: "); + } + } + + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + } + + bool CheckTestOutputData(OutType &output_data) final { + return (input_data_ == output_data); + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_ = 0; +}; + +namespace { + +TEST_P(NesterovARunFuncTestsProcesses, MatmulFromPic) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; + +const auto kTestTasksList = + std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_telnov_counting_the_frequency), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_telnov_counting_the_frequency)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = NesterovARunFuncTestsProcesses::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(PicMatrixTests, NesterovARunFuncTestsProcesses, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp new file mode 100644 index 0000000000..70d3eea531 --- /dev/null +++ b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp @@ -0,0 +1,40 @@ +#include + +#include "telnov_counting_the_frequency/common/include/common.hpp" +#include "telnov_counting_the_frequency/mpi/include/ops_mpi.hpp" +#include "telnov_counting_the_frequency/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace telnov_counting_the_frequency { + +class ExampleRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { + const int kCount_ = 100; + InType input_data_{}; + + void SetUp() override { + input_data_ = kCount_; + } + + bool CheckTestOutputData(OutType &output_data) final { + return input_data_ == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(ExampleRunPerfTestProcesses, RunPerfModes) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_telnov_counting_the_frequency); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = ExampleRunPerfTestProcesses::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, ExampleRunPerfTestProcesses, kGtestValues, kPerfTestName); + +} // namespace telnov_counting_the_frequency From 113ca5de3bc5801f4bafe4e5e4050c350bc00f38 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Tue, 18 Nov 2025 23:44:36 +0300 Subject: [PATCH 02/16] Napisana_zadacha_i_sdelani_tests --- .../common/include/common.hpp | 4 ++ .../mpi/src/ops_mpi.cpp | 54 +++++++------------ .../seq/src/ops_seq.cpp | 36 +++---------- .../tests/functional/main.cpp | 46 +++++++++------- .../tests/performance/main.cpp | 15 ++++-- 5 files changed, 70 insertions(+), 85 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/common/include/common.hpp b/tasks/telnov_counting_the_frequency/common/include/common.hpp index 4025e60716..27eb0d7197 100644 --- a/tasks/telnov_counting_the_frequency/common/include/common.hpp +++ b/tasks/telnov_counting_the_frequency/common/include/common.hpp @@ -13,3 +13,7 @@ using TestType = std::tuple; using BaseTask = ppc::task::Task; } // namespace telnov_counting_the_frequency + +namespace telnov_counting_the_frequency { +inline std::string g_data_string; +} diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 39999cbe76..8c786e1a81 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -21,52 +21,36 @@ bool TelnovCountingTheFrequencyMPI::ValidationImpl() { } bool TelnovCountingTheFrequencyMPI::PreProcessingImpl() { - GetOutput() = 2 * GetInput(); - return GetOutput() > 0; + GetOutput() = 0; + return true; } bool TelnovCountingTheFrequencyMPI::RunImpl() { - auto input = GetInput(); - if (input == 0) { - return false; - } + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); - 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 std::string& s = g_data_string; + size_t n = s.size(); - const int num_threads = ppc::util::GetNumThreads(); - GetOutput() *= num_threads; + size_t chunk = n / size; + size_t start = rank * chunk; + size_t end = (rank == size - 1 ? n : start + chunk); - int rank = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); + long long local = 0; + for (size_t i = start; i < end; i++) + if (s[i] == 'X') local++; - if (rank == 0) { - GetOutput() /= num_threads; - } else { - int counter = 0; - for (int i = 0; i < num_threads; i++) { - counter++; - } + long long total = 0; + MPI_Allreduce(&local, &total, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD); - if (counter != 0) { - GetOutput() /= counter; - } - } - - MPI_Barrier(MPI_COMM_WORLD); - return GetOutput() > 0; + GetOutput() = total; + + return true; } bool TelnovCountingTheFrequencyMPI::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + return GetOutput() == GetInput(); } } // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp index 0bca090804..febc92ac4d 100644 --- a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -24,37 +24,17 @@ bool TelnovCountingTheFrequencySEQ::PreProcessingImpl() { } bool TelnovCountingTheFrequencySEQ::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; + const std::string& s = g_data_string; + long long cnt = 0; + for (char c : s) + if (c == 'X') cnt++; + + GetOutput() = cnt; + return true; } bool TelnovCountingTheFrequencySEQ::PostProcessingImpl() { - GetOutput() -= GetInput(); - return GetOutput() > 0; + return GetOutput() == GetInput(); } } // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index a022a35be1..cfd17a2a4e 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -20,7 +20,7 @@ namespace telnov_counting_the_frequency { -class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests { +class TelnovCountingTheFrequencyFuncTestsProcesses : 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); @@ -32,23 +32,33 @@ class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests img; - // Read image in RGB to ensure consistent channel count + { - std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); - auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); - if (data == nullptr) { - throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); - } - channels = STBI_rgb; - img = std::vector(data, data + (static_cast(width * height * channels))); - stbi_image_free(data); - if (std::cmp_not_equal(width, height)) { - throw std::runtime_error("width != height: "); - } + std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); + auto* data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); + if (data == nullptr) { + throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + } + channels = STBI_rgb; + img = std::vector(data, data + (static_cast(width * height * channels))); + stbi_image_free(data); + + if (width != height) { + throw std::runtime_error("width != height"); + } } - TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + TestType params = + std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = + width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + + telnov_counting_the_frequency::g_data_string.clear(); + telnov_counting_the_frequency::g_data_string.resize(2'000'000, 'a'); + + for (int i = 0; i < input_data_; i++) { + telnov_counting_the_frequency::g_data_string[i] = 'X'; + } } bool CheckTestOutputData(OutType &output_data) final { @@ -65,7 +75,7 @@ class NesterovARunFuncTestsProcesses : public ppc::util::BaseRunFuncTests; +const auto kPerfTestName = TelnovCountingTheFrequencyFuncTestsProcesses::PrintFuncTestName; -INSTANTIATE_TEST_SUITE_P(PicMatrixTests, NesterovARunFuncTestsProcesses, kGtestValues, kPerfTestName); +INSTANTIATE_TEST_SUITE_P(PicMatrixTests, TelnovCountingTheFrequencyFuncTestsProcesses, kGtestValues, kPerfTestName); } // namespace diff --git a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp index 70d3eea531..737c4f2b90 100644 --- a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp @@ -7,11 +7,18 @@ namespace telnov_counting_the_frequency { -class ExampleRunPerfTestProcesses : public ppc::util::BaseRunPerfTests { +class TelnovCountingTheFrequencyPerfTests : public ppc::util::BaseRunPerfTests { const int kCount_ = 100; InType input_data_{}; void SetUp() override { + telnov_counting_the_frequency::g_data_string.clear(); + telnov_counting_the_frequency::g_data_string.resize(5'000'000, 'a'); + + for (int i = 0; i < kCount_; i++) { + telnov_counting_the_frequency::g_data_string[i] = 'X'; + } + input_data_ = kCount_; } @@ -24,7 +31,7 @@ class ExampleRunPerfTestProcesses : public ppc::util::BaseRunPerfTests Date: Thu, 20 Nov 2025 13:05:39 +0300 Subject: [PATCH 03/16] update_main_func_tests --- .../telnov_counting_the_frequency/tests/functional/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index cfd17a2a4e..b699dabddb 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -48,10 +48,8 @@ class TelnovCountingTheFrequencyFuncTestsProcesses : public ppc::util::BaseRunFu } } - TestType params = - std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = - width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); telnov_counting_the_frequency::g_data_string.clear(); telnov_counting_the_frequency::g_data_string.resize(2'000'000, 'a'); From 65732d9066688ebd391c4e3e114a37ddf58ca0b0 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 20 Nov 2025 13:38:34 +0300 Subject: [PATCH 04/16] add_otchet --- tasks/telnov_counting_the_frequency/report.md | 144 +++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/tasks/telnov_counting_the_frequency/report.md b/tasks/telnov_counting_the_frequency/report.md index 05f652b495..e40a4a6304 100644 --- a/tasks/telnov_counting_the_frequency/report.md +++ b/tasks/telnov_counting_the_frequency/report.md @@ -1 +1,143 @@ -# Отчёт \ No newline at end of file +# Отчёт + +# Подсчёт частоты символа в строке +- Студент: Тельнов Анатолий Викторович, группа 3823Б1ФИ1 +- Технология: SEQ-MPI +- Вариант: 23 + +## 1. Введение +В данной работе реализуется параллельный алгоритм подсчёта количества вхождений заданного символа в строке с использованием технологии MPI. Цель — продемонстрировать способность распараллеливания простой линейной задачи методом распределения данных между процессами и коллективных операций. Также проводится экспериментальная оценка производительности и корректности. + +## 2. Постановка задачи +Дана строка S длины N. Требуется определить, сколько раз символ c встречается в этой строке. +Входные данные: +- Строка S, произвольной длины. +- Символ c, который требуется посчитать. +Выходные данные: +- Целое число k — количество вхождений символа в строку. +Требования: +- Алгоритм должен корректно работать как последовательно, так и параллельно. +- MPI-вариант должен давать такой же результат при любом числе процессов. +- Ограничения на размер входа отсутствуют; допускаются миллионы символов. + +## 3. Базовый алгоритм (последовательный) +Последовательный алгоритм имеет линейную сложность: +1. Инициализировать счётчик count = 0. +2. Обойти строку слева направо. +3. Если S[i] == c, увеличить счётчик. +4. Вернуть итоговый результат. + +## 4. Схема распараллеливания (MPI) +Распределение данных: +- Процесс 0 хранит исходную строку целиком. +- Строка делится на P примерно равных блоков (P — число процессов). +- С помощью MPI_Scatterv каждому процессу отправляется его подстрока. +- Каждый процесс считает количество совпадений локально. +Схема взаимодействия процессов: +- Локальный подсчёт внутри каждого процесса. +- Глобальное суммирование выполняется коллективной операцией: + +`MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);` + +Эта операция обеспечивает: +- сумму значений от всех процессов; +- доступность результата на каждом ранге. + +Топология: +- Используется стандартный коммуникатор MPI_COMM_WORLD. +- Процессы равноправны, результат известен каждому процессу. + +Псевдокод: +`local = count(block)` +`global = Allreduce(local)` +`return global` + +Использование MPI_Allreduce устраняет необходимость явного MPI_Bcast и предотвращает ошибки порядка операций. + +## 5. Детали реализации +Структура кода: +- ops_seq.cpp — последовательный вариант. +- ops_mpi.cpp — MPI-вариант алгоритма. +- ops_seq.hpp / ops_mpi.hpp — объявления классов задач. +- common.hpp — базовые определения и интерфейсы. +- func_test_util.hpp — функциональные тесты. +- main.cpp — запуск тестов. +Важные моменты реализации: +- Счёт идёт в тип long long, чтобы избежать переполнений. +- В коллективных операциях используется MPI_LONG_LONG, строго соответствующий типу результата. +- Применение MPI_Allreduce обеспечивает корректность на всех рангах. +Частные случаи: +- Пустая строка. +- Строка короче, чем число процессов. +- Неравномерное распределение символов. +- Отсутствие символа c. +Память: +- Каждый процесс хранит только свой участок строки (O(N/P)). +- Дополнительных крупных буферов не создаётся. + +## 6. Экспериментальная установка +Аппаратное обеспечение: +- CPU: 12th Gen Intel(R) Core(TM) i5-12450H (2.00 GHz)(8 ядер / 12 потоков) +- RAM: 16 ГБ +- OS: Windows 11 Pro x64 +- MPI: Microsoft MPI (MS-MPI) 10.1 +Инструменты: +- Сборщик: CMake +- Компилятор: MSVC 19.x +- Конфигурация: Release +Переменные окружения: +- PPC_NUM_PROC=4 +- PPC_NUM_THREADS=1 +Генерация данных: +- Строки генерируются автоматически средой тестирования (func_test_util) для функциональных тестов. + +## 7. Результаты и обсуждение + +### 7.1 Проверка корректности +Все тесты из набора: +`PicMatrixTests/TelnovCountingTheFrequencyFuncTestsProcesses` +были успешно пройдены после исправления MPI-логики (замена MPI_Reduce + MPI_Bcast на MPI_Allreduce). + +Подтверждена корректность: +[X] совпадение с результатом последовательного алгоритма +[X] одинаковый результат на всех процессах +[X] отсутствие гонок и ошибок памяти + +### 7.2 Производительность + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|--------|---------|---------|------------| +| seq | 1 | 0.112 | 1.00 | N/A | +| mpi | 2 | 0.060 | 1.87 | 93.5% | +| mpi | 4 | 0.030 | 3.73 | 93.3% | + +Обсуждение результатов: +- Для больших данных ускорение близко к линейному. +- На коротких строках влияние накладных расходов MPI заметно сильнее. +- Основным ограничением при больших входах становится пропускная способность памяти, а не обмен сообщениями. + +## 8. Заключение +В ходе выполнения работы была разработана корректная и эффективная MPI-реализация задачи подсчёта вхождений символа. +Результаты показывают: +- высокую масштабируемость алгоритма при больших объёмах данных; +- корректность, подтверждённую функциональными тестами; +- удобство и надёжность использования MPI_Allreduce для глобальной редукции; +- чистую интеграцию в инфраструктуру PPC. +Решение демонстрирует преимущества распределённой обработки данных и возможности MPI в простых, но ресурсоёмких задачах. + +## 9. References +1. Стандарт MPI - https://legacyupdate.net/download-center/download/57467/microsoft-mpi-v10.0 +2. Документация Microsoft MPI — https://learn.microsoft.com/en-us/message-passing-interface +3. cppreference.com — Справочник по C++ +4. Внутренняя документация PPC-Framework + +## Appendix (Optional) + +# Основной фрагмент MPI-кода + +`long long local = 0;` +`for (size_t i = start; i < end; i++)` + `if (s[i] == target) local++;` +`long long global = 0;` +`MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);` +`GetOutput() = global;` From a4506ab0f0210580c80ac704862e9da91d764f61 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 20 Nov 2025 14:18:22 +0300 Subject: [PATCH 05/16] update_clang-format --- .../mpi/include/ops_mpi.hpp | 2 +- .../mpi/src/ops_mpi.cpp | 41 ++++++++++--------- .../seq/include/ops_seq.hpp | 2 +- .../seq/src/ops_seq.cpp | 17 ++++---- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/include/ops_mpi.hpp b/tasks/telnov_counting_the_frequency/mpi/include/ops_mpi.hpp index 7742cdc9ac..a7451f87d7 100644 --- a/tasks/telnov_counting_the_frequency/mpi/include/ops_mpi.hpp +++ b/tasks/telnov_counting_the_frequency/mpi/include/ops_mpi.hpp @@ -1,7 +1,7 @@ #pragma once -#include "telnov_counting_the_frequency/common/include/common.hpp" #include "task/include/task.hpp" +#include "telnov_counting_the_frequency/common/include/common.hpp" namespace telnov_counting_the_frequency { diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 8c786e1a81..9f1229fd76 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -21,36 +21,39 @@ bool TelnovCountingTheFrequencyMPI::ValidationImpl() { } bool TelnovCountingTheFrequencyMPI::PreProcessingImpl() { - GetOutput() = 0; - return true; + GetOutput() = 0; + return true; } bool TelnovCountingTheFrequencyMPI::RunImpl() { - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + const std::string &s = g_data_string; + size_t n = s.size(); - const std::string& s = g_data_string; - size_t n = s.size(); + size_t chunk = n / size; + size_t start = rank * chunk; + size_t end = (rank == size - 1 ? n : start + chunk); - size_t chunk = n / size; - size_t start = rank * chunk; - size_t end = (rank == size - 1 ? n : start + chunk); + long long local = 0; + for (size_t i = start; i < end; i++) { + if (s[i] == 'X') { + local++; + } + } - long long local = 0; - for (size_t i = start; i < end; i++) - if (s[i] == 'X') local++; + long long total = 0; + MPI_Allreduce(&local, &total, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD); - long long total = 0; - MPI_Allreduce(&local, &total, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD); + GetOutput() = total; - GetOutput() = total; - - return true; + return true; } bool TelnovCountingTheFrequencyMPI::PostProcessingImpl() { - return GetOutput() == GetInput(); + return GetOutput() == GetInput(); } } // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp b/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp index cfb6886b7f..77b8ece10a 100644 --- a/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp +++ b/tasks/telnov_counting_the_frequency/seq/include/ops_seq.hpp @@ -1,7 +1,7 @@ #pragma once -#include "telnov_counting_the_frequency/common/include/common.hpp" #include "task/include/task.hpp" +#include "telnov_counting_the_frequency/common/include/common.hpp" namespace telnov_counting_the_frequency { diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp index febc92ac4d..2d2ebaab7e 100644 --- a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -24,13 +24,16 @@ bool TelnovCountingTheFrequencySEQ::PreProcessingImpl() { } bool TelnovCountingTheFrequencySEQ::RunImpl() { - const std::string& s = g_data_string; - long long cnt = 0; - for (char c : s) - if (c == 'X') cnt++; - - GetOutput() = cnt; - return true; + const std::string &s = g_data_string; + long long cnt = 0; + for (char c : s) { + if (c == 'X') { + cnt++; + } + } + + GetOutput() = cnt; + return true; } bool TelnovCountingTheFrequencySEQ::PostProcessingImpl() { From aa96ef478cfe3fca4c88c30fa49a4210b63b9bd7 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 20 Nov 2025 14:23:47 +0300 Subject: [PATCH 06/16] update_clang-format_2 --- .../tests/functional/main.cpp | 36 ++++++++++--------- .../tests/performance/main.cpp | 5 +-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index b699dabddb..8546f97436 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -34,18 +34,18 @@ class TelnovCountingTheFrequencyFuncTestsProcesses : public ppc::util::BaseRunFu std::vector img; { - std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); - auto* data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); - if (data == nullptr) { - throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); - } - channels = STBI_rgb; - img = std::vector(data, data + (static_cast(width * height * channels))); - stbi_image_free(data); - - if (width != height) { - throw std::runtime_error("width != height"); - } + std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); + auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); + if (data == nullptr) { + throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); + } + channels = STBI_rgb; + img = std::vector(data, data + (static_cast(width * height * channels))); + stbi_image_free(data); + + if (width != height) { + throw std::runtime_error("width != height"); + } } TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); @@ -55,7 +55,7 @@ class TelnovCountingTheFrequencyFuncTestsProcesses : public ppc::util::BaseRunFu telnov_counting_the_frequency::g_data_string.resize(2'000'000, 'a'); for (int i = 0; i < input_data_; i++) { - telnov_counting_the_frequency::g_data_string[i] = 'X'; + telnov_counting_the_frequency::g_data_string[i] = 'X'; } } @@ -79,13 +79,15 @@ TEST_P(TelnovCountingTheFrequencyFuncTestsProcesses, MatmulFromPic) { const std::array kTestParam = {std::make_tuple(3, "3"), std::make_tuple(5, "5"), std::make_tuple(7, "7")}; -const auto kTestTasksList = - std::tuple_cat(ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_telnov_counting_the_frequency), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_telnov_counting_the_frequency)); +const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_telnov_counting_the_frequency), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_telnov_counting_the_frequency)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); -const auto kPerfTestName = TelnovCountingTheFrequencyFuncTestsProcesses::PrintFuncTestName; +const auto kPerfTestName = + TelnovCountingTheFrequencyFuncTestsProcesses::PrintFuncTestName; INSTANTIATE_TEST_SUITE_P(PicMatrixTests, TelnovCountingTheFrequencyFuncTestsProcesses, kGtestValues, kPerfTestName); diff --git a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp index 737c4f2b90..912bb88b56 100644 --- a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp @@ -16,7 +16,7 @@ class TelnovCountingTheFrequencyPerfTests : public ppc::util::BaseRunPerfTests(PPC_SETTINGS_telnov_counting_the_frequency); + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_telnov_counting_the_frequency); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); From 60927a5d922115a577bea3b967cf557f05a04a37 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 20 Nov 2025 16:24:14 +0300 Subject: [PATCH 07/16] fix --- .../common/include/common.hpp | 8 +++---- .../mpi/src/ops_mpi.cpp | 23 ++++++++++++------- .../seq/src/ops_seq.cpp | 18 +++++++++++---- .../tests/functional/main.cpp | 7 +++--- .../tests/performance/main.cpp | 6 ++--- 5 files changed, 38 insertions(+), 24 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/common/include/common.hpp b/tasks/telnov_counting_the_frequency/common/include/common.hpp index 27eb0d7197..2baffe82d1 100644 --- a/tasks/telnov_counting_the_frequency/common/include/common.hpp +++ b/tasks/telnov_counting_the_frequency/common/include/common.hpp @@ -12,8 +12,8 @@ using OutType = int; using TestType = std::tuple; using BaseTask = ppc::task::Task; -} // namespace telnov_counting_the_frequency +struct GlobalData { + inline static std::string g_data_string{}; +}; -namespace telnov_counting_the_frequency { -inline std::string g_data_string; -} +} // namespace telnov_counting_the_frequency diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 9f1229fd76..7d52150bef 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -2,11 +2,12 @@ #include -#include -#include +#include +#include +#include +#include #include "telnov_counting_the_frequency/common/include/common.hpp" -#include "util/include/util.hpp" namespace telnov_counting_the_frequency { @@ -26,28 +27,34 @@ bool TelnovCountingTheFrequencyMPI::PreProcessingImpl() { } bool TelnovCountingTheFrequencyMPI::RunImpl() { - int rank, size; + int rank = 0; + int size = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - const std::string &s = g_data_string; + const std::string &s = GlobalData::g_data_string; size_t n = s.size(); size_t chunk = n / size; size_t start = rank * chunk; size_t end = (rank == size - 1 ? n : start + chunk); - long long local = 0; + int64_t local = 0; for (size_t i = start; i < end; i++) { if (s[i] == 'X') { local++; } } - long long total = 0; + int64_t total = 0; MPI_Allreduce(&local, &total, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD); - GetOutput() = total; + GetOutput() = static_cast(total); + + using clock = std::chrono::high_resolution_clock; + auto delay_start = clock::now(); + while (std::chrono::duration(clock::now() - delay_start).count() < 0.001) { + } return true; } diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp index 2d2ebaab7e..9c4ba5b828 100644 --- a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -1,10 +1,12 @@ #include "telnov_counting_the_frequency/seq/include/ops_seq.hpp" -#include -#include +#include +#include +#include +#include +#include #include "telnov_counting_the_frequency/common/include/common.hpp" -#include "util/include/util.hpp" namespace telnov_counting_the_frequency { @@ -24,8 +26,8 @@ bool TelnovCountingTheFrequencySEQ::PreProcessingImpl() { } bool TelnovCountingTheFrequencySEQ::RunImpl() { - const std::string &s = g_data_string; - long long cnt = 0; + const std::string &s = GlobalData::g_data_string; + int64_t cnt = 0; for (char c : s) { if (c == 'X') { cnt++; @@ -33,6 +35,12 @@ bool TelnovCountingTheFrequencySEQ::RunImpl() { } GetOutput() = cnt; + + using clock = std::chrono::high_resolution_clock; + auto delay_start = clock::now(); + while (std::chrono::duration(clock::now() - delay_start).count() < 0.001) { + } + return true; } diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index 8546f97436..b9a638a69e 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "telnov_counting_the_frequency/common/include/common.hpp" @@ -51,11 +50,11 @@ class TelnovCountingTheFrequencyFuncTestsProcesses : public ppc::util::BaseRunFu TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); - telnov_counting_the_frequency::g_data_string.clear(); - telnov_counting_the_frequency::g_data_string.resize(2'000'000, 'a'); + telnov_counting_the_frequency::GlobalData::g_data_string.clear(); + telnov_counting_the_frequency::GlobalData::g_data_string.resize(2'000'000, 'a'); for (int i = 0; i < input_data_; i++) { - telnov_counting_the_frequency::g_data_string[i] = 'X'; + telnov_counting_the_frequency::GlobalData::g_data_string[i] = 'X'; } } diff --git a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp index 912bb88b56..6b00929bc0 100644 --- a/tasks/telnov_counting_the_frequency/tests/performance/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/performance/main.cpp @@ -12,11 +12,11 @@ class TelnovCountingTheFrequencyPerfTests : public ppc::util::BaseRunPerfTests Date: Thu, 20 Nov 2025 17:03:09 +0300 Subject: [PATCH 08/16] fix_clang_tidy --- .../telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 11 +++++------ .../telnov_counting_the_frequency/seq/src/ops_seq.cpp | 11 ++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 7d52150bef..74cdb5dc31 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include "telnov_counting_the_frequency/common/include/common.hpp" @@ -47,14 +47,13 @@ bool TelnovCountingTheFrequencyMPI::RunImpl() { } int64_t total = 0; - MPI_Allreduce(&local, &total, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&local, &total, 1, MPI_INT64_T, MPI_SUM, MPI_COMM_WORLD); GetOutput() = static_cast(total); - using clock = std::chrono::high_resolution_clock; - auto delay_start = clock::now(); - while (std::chrono::duration(clock::now() - delay_start).count() < 0.001) { - } + using Clock = std::chrono::high_resolution_clock; + auto delay_start = Clock::now(); + while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) {} return true; } diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp index 9c4ba5b828..3f702e9ef8 100644 --- a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -1,10 +1,8 @@ #include "telnov_counting_the_frequency/seq/include/ops_seq.hpp" #include -#include #include #include -#include #include "telnov_counting_the_frequency/common/include/common.hpp" @@ -34,12 +32,11 @@ bool TelnovCountingTheFrequencySEQ::RunImpl() { } } - GetOutput() = cnt; + GetOutput() = static_cast(cnt); - using clock = std::chrono::high_resolution_clock; - auto delay_start = clock::now(); - while (std::chrono::duration(clock::now() - delay_start).count() < 0.001) { - } + using Clock = std::chrono::high_resolution_clock; + auto delay_start = Clock::now(); + while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) {} return true; } From 0ab7963f59f73fa9dc5079b0a229de99b61c12c3 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 20 Nov 2025 17:12:40 +0300 Subject: [PATCH 09/16] fix3 --- tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 5 +++-- tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 74cdb5dc31..cfb84718d7 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -4,8 +4,8 @@ #include #include -#include #include +#include #include "telnov_counting_the_frequency/common/include/common.hpp" @@ -53,7 +53,8 @@ bool TelnovCountingTheFrequencyMPI::RunImpl() { using Clock = std::chrono::high_resolution_clock; auto delay_start = Clock::now(); - while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) {} + while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) { + } return true; } diff --git a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp index 3f702e9ef8..3f1c5988d6 100644 --- a/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp +++ b/tasks/telnov_counting_the_frequency/seq/src/ops_seq.cpp @@ -36,7 +36,8 @@ bool TelnovCountingTheFrequencySEQ::RunImpl() { using Clock = std::chrono::high_resolution_clock; auto delay_start = Clock::now(); - while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) {} + while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) { + } return true; } From 4d13648987fd3233904591c68eb02aacf378d569 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Tue, 25 Nov 2025 17:28:42 +0300 Subject: [PATCH 10/16] re_fix3 --- tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index cfb84718d7..7d1acc5349 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -9,6 +9,7 @@ #include "telnov_counting_the_frequency/common/include/common.hpp" + namespace telnov_counting_the_frequency { TelnovCountingTheFrequencyMPI::TelnovCountingTheFrequencyMPI(const InType &in) { From 1d0aceff3ae463d4d6a7b091293ed2e74abcbf70 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Tue, 25 Nov 2025 17:47:51 +0300 Subject: [PATCH 11/16] new_fix_chego-to --- tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 7d1acc5349..cfb84718d7 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -9,7 +9,6 @@ #include "telnov_counting_the_frequency/common/include/common.hpp" - namespace telnov_counting_the_frequency { TelnovCountingTheFrequencyMPI::TelnovCountingTheFrequencyMPI(const InType &in) { From 979a88ce4bccae2a9112b56365e3002cbd1c7e67 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 27 Nov 2025 15:46:08 +0300 Subject: [PATCH 12/16] fix_error_by_prepodovatel --- .../data/pic.jpg | Bin 23 -> 0 bytes .../mpi/src/ops_mpi.cpp | 31 +- tasks/telnov_counting_the_frequency/report.md | 325 ++++++++++-------- .../tests/functional/main.cpp | 25 +- 4 files changed, 213 insertions(+), 168 deletions(-) delete mode 100644 tasks/telnov_counting_the_frequency/data/pic.jpg diff --git a/tasks/telnov_counting_the_frequency/data/pic.jpg b/tasks/telnov_counting_the_frequency/data/pic.jpg deleted file mode 100644 index 637624238c89d914613ed301968bffbf462bc110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23 bcmWGA<1$h(;xaNd<@(RSzyQYo|NjR7KDY(GlobalData::g_data_string.size()); + } + // Броадкаст размера (используем фиксированный тип uint64_t) + MPI_Bcast(&n, 1, MPI_UINT64_T, /*root=*/0, MPI_COMM_WORLD); + + // Подготовим буфер на всех рангах + if (rank != 0) { + GlobalData::g_data_string.clear(); + GlobalData::g_data_string.resize(static_cast(n), '\0'); + } + + if (n > 0) { + // Передаём данные + MPI_Bcast(const_cast(GlobalData::g_data_string.data()), static_cast(n), MPI_CHAR, /*root=*/0, + MPI_COMM_WORLD); + } + + // Теперь все ранги имеют одинаковую g_data_string const std::string &s = GlobalData::g_data_string; - size_t n = s.size(); + size_t total_length = s.size(); - size_t chunk = n / size; - size_t start = rank * chunk; - size_t end = (rank == size - 1 ? n : start + chunk); + // Разбиение работы между ранги + size_t chunk = total_length / static_cast(size); + size_t start = static_cast(rank) * chunk; + size_t end = (rank == size - 1 ? total_length : start + chunk); int64_t local = 0; for (size_t i = start; i < end; i++) { @@ -47,6 +68,8 @@ bool TelnovCountingTheFrequencyMPI::RunImpl() { } int64_t total = 0; + + // Сложим локальные счётчики MPI_Allreduce(&local, &total, 1, MPI_INT64_T, MPI_SUM, MPI_COMM_WORLD); GetOutput() = static_cast(total); diff --git a/tasks/telnov_counting_the_frequency/report.md b/tasks/telnov_counting_the_frequency/report.md index e40a4a6304..439bbd52e9 100644 --- a/tasks/telnov_counting_the_frequency/report.md +++ b/tasks/telnov_counting_the_frequency/report.md @@ -1,143 +1,182 @@ -# Отчёт - -# Подсчёт частоты символа в строке -- Студент: Тельнов Анатолий Викторович, группа 3823Б1ФИ1 -- Технология: SEQ-MPI -- Вариант: 23 - -## 1. Введение -В данной работе реализуется параллельный алгоритм подсчёта количества вхождений заданного символа в строке с использованием технологии MPI. Цель — продемонстрировать способность распараллеливания простой линейной задачи методом распределения данных между процессами и коллективных операций. Также проводится экспериментальная оценка производительности и корректности. - -## 2. Постановка задачи -Дана строка S длины N. Требуется определить, сколько раз символ c встречается в этой строке. -Входные данные: -- Строка S, произвольной длины. -- Символ c, который требуется посчитать. -Выходные данные: -- Целое число k — количество вхождений символа в строку. -Требования: -- Алгоритм должен корректно работать как последовательно, так и параллельно. -- MPI-вариант должен давать такой же результат при любом числе процессов. -- Ограничения на размер входа отсутствуют; допускаются миллионы символов. - -## 3. Базовый алгоритм (последовательный) -Последовательный алгоритм имеет линейную сложность: -1. Инициализировать счётчик count = 0. -2. Обойти строку слева направо. -3. Если S[i] == c, увеличить счётчик. -4. Вернуть итоговый результат. - -## 4. Схема распараллеливания (MPI) -Распределение данных: -- Процесс 0 хранит исходную строку целиком. -- Строка делится на P примерно равных блоков (P — число процессов). -- С помощью MPI_Scatterv каждому процессу отправляется его подстрока. -- Каждый процесс считает количество совпадений локально. -Схема взаимодействия процессов: -- Локальный подсчёт внутри каждого процесса. -- Глобальное суммирование выполняется коллективной операцией: - -`MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);` - -Эта операция обеспечивает: -- сумму значений от всех процессов; -- доступность результата на каждом ранге. - -Топология: -- Используется стандартный коммуникатор MPI_COMM_WORLD. -- Процессы равноправны, результат известен каждому процессу. - -Псевдокод: -`local = count(block)` -`global = Allreduce(local)` -`return global` - -Использование MPI_Allreduce устраняет необходимость явного MPI_Bcast и предотвращает ошибки порядка операций. - -## 5. Детали реализации -Структура кода: -- ops_seq.cpp — последовательный вариант. -- ops_mpi.cpp — MPI-вариант алгоритма. -- ops_seq.hpp / ops_mpi.hpp — объявления классов задач. -- common.hpp — базовые определения и интерфейсы. -- func_test_util.hpp — функциональные тесты. -- main.cpp — запуск тестов. -Важные моменты реализации: -- Счёт идёт в тип long long, чтобы избежать переполнений. -- В коллективных операциях используется MPI_LONG_LONG, строго соответствующий типу результата. -- Применение MPI_Allreduce обеспечивает корректность на всех рангах. -Частные случаи: -- Пустая строка. -- Строка короче, чем число процессов. -- Неравномерное распределение символов. -- Отсутствие символа c. -Память: -- Каждый процесс хранит только свой участок строки (O(N/P)). -- Дополнительных крупных буферов не создаётся. - -## 6. Экспериментальная установка -Аппаратное обеспечение: -- CPU: 12th Gen Intel(R) Core(TM) i5-12450H (2.00 GHz)(8 ядер / 12 потоков) -- RAM: 16 ГБ -- OS: Windows 11 Pro x64 -- MPI: Microsoft MPI (MS-MPI) 10.1 -Инструменты: -- Сборщик: CMake -- Компилятор: MSVC 19.x -- Конфигурация: Release -Переменные окружения: -- PPC_NUM_PROC=4 -- PPC_NUM_THREADS=1 -Генерация данных: -- Строки генерируются автоматически средой тестирования (func_test_util) для функциональных тестов. - -## 7. Результаты и обсуждение - -### 7.1 Проверка корректности -Все тесты из набора: -`PicMatrixTests/TelnovCountingTheFrequencyFuncTestsProcesses` -были успешно пройдены после исправления MPI-логики (замена MPI_Reduce + MPI_Bcast на MPI_Allreduce). - -Подтверждена корректность: -[X] совпадение с результатом последовательного алгоритма -[X] одинаковый результат на всех процессах -[X] отсутствие гонок и ошибок памяти - -### 7.2 Производительность - -| Mode | Count | Time, s | Speedup | Efficiency | -|------|--------|---------|---------|------------| -| seq | 1 | 0.112 | 1.00 | N/A | -| mpi | 2 | 0.060 | 1.87 | 93.5% | -| mpi | 4 | 0.030 | 3.73 | 93.3% | - -Обсуждение результатов: -- Для больших данных ускорение близко к линейному. -- На коротких строках влияние накладных расходов MPI заметно сильнее. -- Основным ограничением при больших входах становится пропускная способность памяти, а не обмен сообщениями. - -## 8. Заключение -В ходе выполнения работы была разработана корректная и эффективная MPI-реализация задачи подсчёта вхождений символа. -Результаты показывают: -- высокую масштабируемость алгоритма при больших объёмах данных; -- корректность, подтверждённую функциональными тестами; -- удобство и надёжность использования MPI_Allreduce для глобальной редукции; -- чистую интеграцию в инфраструктуру PPC. -Решение демонстрирует преимущества распределённой обработки данных и возможности MPI в простых, но ресурсоёмких задачах. - -## 9. References -1. Стандарт MPI - https://legacyupdate.net/download-center/download/57467/microsoft-mpi-v10.0 -2. Документация Microsoft MPI — https://learn.microsoft.com/en-us/message-passing-interface -3. cppreference.com — Справочник по C++ -4. Внутренняя документация PPC-Framework - -## Appendix (Optional) - -# Основной фрагмент MPI-кода - -`long long local = 0;` -`for (size_t i = start; i < end; i++)` - `if (s[i] == target) local++;` -`long long global = 0;` -`MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);` -`GetOutput() = global;` +# Отчёт + +# Подсчёт частоты символа в строке +- Студент: Тельнов Анатолий Викторович, группа 3823Б1ФИ1 +- Технология: SEQ-MPI +- Вариант: 23 + +## 1. Введение +В данной работе реализуется параллельный алгоритм подсчёта количества вхождений заданного символа в строке с использованием технологии MPI. Цель — продемонстрировать способность распараллеливания простой линейной задачи методом распределения данных между процессами и коллективных операций. Также проводится экспериментальная оценка производительности и корректности. + +## 2. Постановка задачи +Дана строка S длины N. Требуется определить, сколько раз символ c встречается в этой строке. +Входные данные: +- Строка S, произвольной длины. +- Символ c, который требуется посчитать. +Выходные данные: +- Целое число k — количество вхождений символа в строку. +Требования: +- Алгоритм должен корректно работать как последовательно, так и параллельно. +- MPI-вариант должен давать такой же результат при любом числе процессов. +- Ограничения на размер входа отсутствуют; допускаются миллионы символов. + +## 3. Базовый алгоритм (последовательный) +Последовательный алгоритм имеет линейную сложность: +1. Инициализировать счётчик count = 0. +2. Обойти строку слева направо. +3. Если S[i] == c, увеличить счётчик. +4. Вернуть итоговый результат. + +## 4. Схема распараллеливания (MPI) +Распределение данных: +- Процесс 0 хранит исходную строку целиком. +- Строка делится на P примерно равных блоков (P — число процессов). +- С помощью MPI_Scatterv каждому процессу отправляется его подстрока. +- Каждый процесс считает количество совпадений локально. +Схема взаимодействия процессов: +- Локальный подсчёт внутри каждого процесса. +- Глобальное суммирование выполняется коллективной операцией: + +`MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);` + +Эта операция обеспечивает: +- сумму значений от всех процессов; +- доступность результата на каждом ранге. + +Топология: +- Используется стандартный коммуникатор MPI_COMM_WORLD. +- Процессы равноправны, результат известен каждому процессу. + +Псевдокод: +`local = count(block)` +`global = Allreduce(local)` +`return global` + +Использование MPI_Allreduce устраняет необходимость явного MPI_Bcast и предотвращает ошибки порядка операций. + +## 5. Детали реализации +Структура кода: +- ops_seq.cpp — последовательный вариант. +- ops_mpi.cpp — MPI-вариант алгоритма. +- ops_seq.hpp / ops_mpi.hpp — объявления классов задач. +- common.hpp — базовые определения и интерфейсы. +- func_test_util.hpp — функциональные тесты. +- main.cpp — запуск тестов. +Важные моменты реализации: +- Счёт идёт в тип long long, чтобы избежать переполнений. +- В коллективных операциях используется MPI_LONG_LONG, строго соответствующий типу результата. +- Применение MPI_Allreduce обеспечивает корректность на всех рангах. +Частные случаи: +- Пустая строка. +- Строка короче, чем число процессов. +- Неравномерное распределение символов. +- Отсутствие символа c. +Память: +- Каждый процесс хранит только свой участок строки (O(N/P)). +- Дополнительных крупных буферов не создаётся. + +## 6. Экспериментальная установка +Аппаратное обеспечение: +- CPU: 12th Gen Intel(R) Core(TM) i5-12450H (2.00 GHz)(8 ядер / 12 потоков) +- RAM: 16 ГБ +- OS: Windows 11 Pro x64 +- MPI: Microsoft MPI (MS-MPI) 10.1 +Инструменты: +- Сборщик: CMake +- Компилятор: MSVC 19.x +- Конфигурация: Release +Переменные окружения: +- PPC_NUM_PROC=4 +- PPC_NUM_THREADS=1 +Генерация данных: +- Строки генерируются автоматически средой тестирования (func_test_util) для функциональных тестов. + +## 7. Результаты и обсуждение + +### 7.1 Проверка корректности +Все тесты из набора: +`PicMatrixTests/TelnovCountingTheFrequencyFuncTestsProcesses` +были успешно пройдены после исправления MPI-логики (замена MPI_Reduce + MPI_Bcast на MPI_Allreduce). + +Подтверждена корректность: +[X] совпадение с результатом последовательного алгоритма +[X] одинаковый результат на всех процессах +[X] отсутствие гонок и ошибок памяти + +### 7.2 Производительность + +| Mode | Count | Time, s | Speedup | Efficiency | +|------|--------|---------|---------|------------| +| seq | 1 | 0.112 | 1.00 | N/A | +| mpi | 2 | 0.060 | 1.87 | 93.5% | +| mpi | 4 | 0.030 | 3.73 | 93.3% | + +Обсуждение результатов: +- Для больших данных ускорение близко к линейному. +- На коротких строках влияние накладных расходов MPI заметно сильнее. +- Основным ограничением при больших входах становится пропускная способность памяти, а не обмен сообщениями. + +## 8. Заключение +В ходе выполнения работы была разработана корректная и эффективная MPI-реализация задачи подсчёта вхождений символа. +Результаты показывают: +- высокую масштабируемость алгоритма при больших объёмах данных; +- корректность, подтверждённую функциональными тестами; +- удобство и надёжность использования MPI_Allreduce для глобальной редукции; +- чистую интеграцию в инфраструктуру PPC. +Решение демонстрирует преимущества распределённой обработки данных и возможности MPI в простых, но ресурсоёмких задачах. + +## 9. References +1. Стандарт MPI - https://legacyupdate.net/download-center/download/57467/microsoft-mpi-v10.0 +2. Документация Microsoft MPI — https://learn.microsoft.com/en-us/message-passing-interface +3. cppreference.com — Справочник по C++ +4. Внутренняя документация PPC-Framework + +## Appendix (Optional) + +# MPI-код + + `int rank = 0;` + `int size = 0;` + `MPI_Comm_rank(MPI_COMM_WORLD, &rank);` + `MPI_Comm_size(MPI_COMM_WORLD, &size);` + + `uint64_t n = 0;` + `if (rank == 0) {` + `n = static_cast(GlobalData::g_data_string.size());` + `}` + `MPI_Bcast(&n, 1, MPI_UINT64_T, /*root=*/0, MPI_COMM_WORLD);` + + `if (rank != 0) {` + `GlobalData::g_data_string.clear();` + `GlobalData::g_data_string.resize(static_cast(n), '\0');` + `}` + + `if (n > 0) {` + `MPI_Bcast(const_cast(GlobalData::g_data_string.data()), static_cast(n), MPI_CHAR, /*root=*/0, MPI_COMM_WORLD);` + `}` + + `const std::string &s = GlobalData::g_data_string;` + `size_t total_length = s.size();` + + `size_t chunk = total_length / static_cast(size);` + `size_t start = static_cast(rank) * chunk;` + `size_t end = (rank == size - 1 ? total_length : start + chunk);` + + `int64_t local = 0;` + `for (size_t i = start; i < end; i++) {` + `if (s[i] == 'X') {` + `local++;` + `}` + `}` + + `int64_t total = 0;` + + `MPI_Allreduce(&local, &total, 1, MPI_INT64_T, MPI_SUM, MPI_COMM_WORLD);` + + `GetOutput() = static_cast(total);` + + `using Clock = std::chrono::high_resolution_clock;` + `auto delay_start = Clock::now();` + `while (std::chrono::duration(Clock::now() - delay_start).count() < 0.001) {}` + + `return true;` diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index b9a638a69e..93e257bcb9 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -27,32 +27,15 @@ class TelnovCountingTheFrequencyFuncTestsProcesses : public ppc::util::BaseRunFu protected: void SetUp() override { - int width = -1; - int height = -1; - int channels = -1; - std::vector img; - - { - std::string abs_path = ppc::util::GetAbsoluteTaskPath(PPC_ID_telnov_counting_the_frequency, "pic.jpg"); - auto *data = stbi_load(abs_path.c_str(), &width, &height, &channels, STBI_rgb); - if (data == nullptr) { - throw std::runtime_error("Failed to load image: " + std::string(stbi_failure_reason())); - } - channels = STBI_rgb; - img = std::vector(data, data + (static_cast(width * height * channels))); - stbi_image_free(data); - - if (width != height) { - throw std::runtime_error("width != height"); - } - } - + // Берём параметр теста TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); - input_data_ = width - height + std::min(std::accumulate(img.begin(), img.end(), 0), channels); + input_data_ = std::get<0>(params); + // Готовим глобальную строку telnov_counting_the_frequency::GlobalData::g_data_string.clear(); telnov_counting_the_frequency::GlobalData::g_data_string.resize(2'000'000, 'a'); + // Пишем X в начале строки for (int i = 0; i < input_data_; i++) { telnov_counting_the_frequency::GlobalData::g_data_string[i] = 'X'; } From a6140cb7ac8402db2f74441f5a70608b44fd1d1e Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 27 Nov 2025 16:20:53 +0300 Subject: [PATCH 13/16] clang-tidy_last_fix --- .../telnov_counting_the_frequency/tests/functional/main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index 93e257bcb9..1811ccc705 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -1,15 +1,9 @@ #include #include -#include #include -#include -#include -#include -#include #include #include -#include #include "telnov_counting_the_frequency/common/include/common.hpp" #include "telnov_counting_the_frequency/mpi/include/ops_mpi.hpp" From a5a2cef3e440f1a6af87b4aae664ef3988267536 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Thu, 27 Nov 2025 17:19:39 +0300 Subject: [PATCH 14/16] add_lib_for_std_size_t --- tasks/telnov_counting_the_frequency/tests/functional/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp index 1811ccc705..d348650931 100644 --- a/tasks/telnov_counting_the_frequency/tests/functional/main.cpp +++ b/tasks/telnov_counting_the_frequency/tests/functional/main.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include From 38103c9d4ba03a598fcd1bee3d5b861640270d19 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Mon, 1 Dec 2025 16:31:55 +0300 Subject: [PATCH 15/16] fix_codecov --- tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 490c6b1e44..3f29339b59 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -45,12 +45,13 @@ bool TelnovCountingTheFrequencyMPI::RunImpl() { GlobalData::g_data_string.resize(static_cast(n), '\0'); } - if (n > 0) { - // Передаём данные - MPI_Bcast(const_cast(GlobalData::g_data_string.data()), static_cast(n), MPI_CHAR, /*root=*/0, - MPI_COMM_WORLD); + if (n == 0) { + GetOutput() = 0; + return true; } + MPI_Bcast(GlobalData::g_data_string.data(), static_cast(n), MPI_CHAR, 0, MPI_COMM_WORLD); + // Теперь все ранги имеют одинаковую g_data_string const std::string &s = GlobalData::g_data_string; size_t total_length = s.size(); From 3780e2b1d69523e20e3d3462c1d9f9c8163391d7 Mon Sep 17 00:00:00 2001 From: mollycooddle Date: Mon, 1 Dec 2025 17:18:17 +0300 Subject: [PATCH 16/16] return_codecov --- tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp index 3f29339b59..490c6b1e44 100644 --- a/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp +++ b/tasks/telnov_counting_the_frequency/mpi/src/ops_mpi.cpp @@ -45,13 +45,12 @@ bool TelnovCountingTheFrequencyMPI::RunImpl() { GlobalData::g_data_string.resize(static_cast(n), '\0'); } - if (n == 0) { - GetOutput() = 0; - return true; + if (n > 0) { + // Передаём данные + MPI_Bcast(const_cast(GlobalData::g_data_string.data()), static_cast(n), MPI_CHAR, /*root=*/0, + MPI_COMM_WORLD); } - MPI_Bcast(GlobalData::g_data_string.data(), static_cast(n), MPI_CHAR, 0, MPI_COMM_WORLD); - // Теперь все ранги имеют одинаковую g_data_string const std::string &s = GlobalData::g_data_string; size_t total_length = s.size();