From e7867cc43efe177f7a90c94b2f68803d6ea1ff36 Mon Sep 17 00:00:00 2001 From: Anton Nikitin Date: Thu, 16 Apr 2026 19:58:41 +0300 Subject: [PATCH] create tbb task --- .../tbb/include/ops_tbb.hpp | 22 +++ .../nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp | 131 ++++++++++++++++++ .../tests/functional/main.cpp | 4 +- .../tests/performance/main.cpp | 7 +- 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 tasks/nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp create mode 100644 tasks/nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp diff --git a/tasks/nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp b/tasks/nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp new file mode 100644 index 000000000..4dcdea8f2 --- /dev/null +++ b/tasks/nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "nikitin_a_monte_carlo/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace nikitin_a_monte_carlo { + +class NikitinAMonteCarloTBB : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kTBB; + } + explicit NikitinAMonteCarloTBB(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace nikitin_a_monte_carlo diff --git a/tasks/nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp b/tasks/nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp new file mode 100644 index 000000000..3f590f906 --- /dev/null +++ b/tasks/nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp @@ -0,0 +1,131 @@ +#include "nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp" + +#include // Современный include для oneTBB +// Альтернатива: #include для старой версии + +#include +#include +#include +#include + +#include "nikitin_a_monte_carlo/common/include/common.hpp" + +namespace nikitin_a_monte_carlo { + +namespace { +// Вспомогательная функция для вычисления значения тестовой функции +double EvaluateFunction(const std::vector &point, FunctionType type) { + if (point.empty()) { + return 0.0; + } + + switch (type) { + case FunctionType::kConstant: + return 1.0; + case FunctionType::kLinear: + return point.at(0); + case FunctionType::kProduct: + if (point.size() < 2) { + return 0.0; + } + return point.at(0) * point.at(1); + case FunctionType::kQuadratic: + if (point.size() < 2) { + return 0.0; + } + return (point.at(0) * point.at(0)) + (point.at(1) * point.at(1)); + case FunctionType::kExponential: + return std::exp(point.at(0)); + default: + return 0.0; + } +} + +// Генерация квазислучайной последовательности Кронекера +double KroneckerSequence(int index, int dimension) { + const std::array primes = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0, 19.0, 23.0, 29.0}; + double alpha = std::sqrt(primes.at(static_cast(dimension % 10))); + alpha = alpha - std::floor(alpha); + return std::fmod(index * alpha, 1.0); +} +} // namespace + +NikitinAMonteCarloTBB::NikitinAMonteCarloTBB(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0.0; +} + +bool NikitinAMonteCarloTBB::ValidationImpl() { + const auto &[lower_bounds, upper_bounds, num_points, func_type] = GetInput(); + + if (lower_bounds.empty() || upper_bounds.empty()) { + return false; + } + + if (lower_bounds.size() != upper_bounds.size()) { + return false; + } + + for (std::size_t i = 0; i < lower_bounds.size(); ++i) { + if (lower_bounds[i] >= upper_bounds[i]) { + return false; + } + } + + return num_points > 0; +} + +bool NikitinAMonteCarloTBB::PreProcessingImpl() { + return true; +} + +bool NikitinAMonteCarloTBB::RunImpl() { + // Получаем входные данные и распаковываем их в обычные переменные + const auto input = GetInput(); + const auto &lower_bounds = std::get<0>(input); + const auto &upper_bounds = std::get<1>(input); + const int num_points = std::get<2>(input); + const FunctionType func_type = std::get<3>(input); + + std::size_t dim = lower_bounds.size(); + + // Вычисление объема области интегрирования + double volume = 1.0; + for (std::size_t i = 0; i < dim; ++i) { + volume *= (upper_bounds[i] - lower_bounds[i]); + } + + double sum = tbb::parallel_reduce(tbb::blocked_range(0, num_points), + 0.0, // Начальное значение редукции + + // Лямбда для вычисления суммы в каждом поддиапазоне + [&](const tbb::blocked_range &range, double local_sum) -> double { + // Локальный буфер для точки (может быть оптимизирован через TLS) + std::vector point(dim); + + for (int i = range.begin(); i != range.end(); ++i) { + // Заполняем точку для текущего i + for (std::size_t j = 0; j < dim; ++j) { + double u = KroneckerSequence(i, static_cast(j)); + point[j] = lower_bounds[j] + (u * (upper_bounds[j] - lower_bounds[j])); + } + local_sum += EvaluateFunction(point, func_type); + } + return local_sum; + }, + + // Функция объединения результатов от разных потоков + [](double x, double y) -> double { return x + y; }); + + double result = volume * sum / static_cast(num_points); + GetOutput() = result; + + return true; +} + +bool NikitinAMonteCarloTBB::PostProcessingImpl() { + return true; +} + +} // namespace nikitin_a_monte_carlo diff --git a/tasks/nikitin_a_monte_carlo/tests/functional/main.cpp b/tasks/nikitin_a_monte_carlo/tests/functional/main.cpp index 593528a4d..c669f3a63 100644 --- a/tasks/nikitin_a_monte_carlo/tests/functional/main.cpp +++ b/tasks/nikitin_a_monte_carlo/tests/functional/main.cpp @@ -10,6 +10,7 @@ #include "nikitin_a_monte_carlo/common/include/common.hpp" #include "nikitin_a_monte_carlo/omp/include/ops_omp.hpp" #include "nikitin_a_monte_carlo/seq/include/ops_seq.hpp" +#include "nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp" #include "util/include/func_test_util.hpp" namespace nikitin_a_monte_carlo { @@ -211,7 +212,8 @@ const std::array kTestParam = { const auto kTestTasksList = std::tuple_cat( ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_nikitin_a_monte_carlo), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_nikitin_a_monte_carlo)); + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_nikitin_a_monte_carlo), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_nikitin_a_monte_carlo)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); diff --git a/tasks/nikitin_a_monte_carlo/tests/performance/main.cpp b/tasks/nikitin_a_monte_carlo/tests/performance/main.cpp index 37b4de0ac..326167e3f 100644 --- a/tasks/nikitin_a_monte_carlo/tests/performance/main.cpp +++ b/tasks/nikitin_a_monte_carlo/tests/performance/main.cpp @@ -8,6 +8,7 @@ #include "nikitin_a_monte_carlo/common/include/common.hpp" #include "nikitin_a_monte_carlo/omp/include/ops_omp.hpp" #include "nikitin_a_monte_carlo/seq/include/ops_seq.hpp" +#include "nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp" #include "util/include/perf_test_util.hpp" namespace nikitin_a_monte_carlo { @@ -84,7 +85,8 @@ TEST_P(NikitinAMonteCarloConstant3DPerfTests, RunPerfModesConstant3D) { const auto kConstant3DPerfTasks = std::tuple_cat(ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo), - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo)); + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo), + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo)); const auto kConstant3DGtestValues = ppc::util::TupleToGTestValues(kConstant3DPerfTasks); const auto kConstant3DPerfTestName = NikitinAMonteCarloConstant3DPerfTests::CustomPerfTestName; @@ -99,7 +101,8 @@ TEST_P(NikitinAMonteCarloLinear4DPerfTests, RunPerfModesLinear4D) { const auto kLinear4DPerfTasks = std::tuple_cat(ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo), - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo)); + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo), + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_nikitin_a_monte_carlo)); const auto kLinear4DGtestValues = ppc::util::TupleToGTestValues(kLinear4DPerfTasks); const auto kLinear4DPerfTestName = NikitinAMonteCarloLinear4DPerfTests::CustomPerfTestName;