diff --git a/tasks/shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp b/tasks/shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp new file mode 100644 index 000000000..8fe00d042 --- /dev/null +++ b/tasks/shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "shkrebko_m_calc_of_integral_rect/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace shkrebko_m_calc_of_integral_rect { + +class ShkrebkoMCalcOfIntegralRectTBB : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kTBB; + } + + explicit ShkrebkoMCalcOfIntegralRectTBB(const InType &in); + + protected: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + private: + [[nodiscard]] double ComputeBlockSum(std::size_t start_idx, std::size_t end_idx, const std::vector &h) const; + + InType local_input_; + double res_ = 0.0; +}; + +} // namespace shkrebko_m_calc_of_integral_rect diff --git a/tasks/shkrebko_m_calc_of_integral_rect/tbb/src/ops_tbb.cpp b/tasks/shkrebko_m_calc_of_integral_rect/tbb/src/ops_tbb.cpp new file mode 100644 index 000000000..71e0cda50 --- /dev/null +++ b/tasks/shkrebko_m_calc_of_integral_rect/tbb/src/ops_tbb.cpp @@ -0,0 +1,120 @@ +#include "shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp" + +#include + +#include +#include +#include +#include +#include + +#include "shkrebko_m_calc_of_integral_rect/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace shkrebko_m_calc_of_integral_rect { + +ShkrebkoMCalcOfIntegralRectTBB::ShkrebkoMCalcOfIntegralRectTBB(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0.0; +} + +bool ShkrebkoMCalcOfIntegralRectTBB::ValidationImpl() { + const auto &input = GetInput(); + + if (!input.func) { + return false; + } + if (input.limits.size() != input.n_steps.size() || input.limits.empty()) { + return false; + } + if (!std::ranges::all_of(input.n_steps, [](int n) { return n > 0; })) { + return false; + } + if (!std::ranges::all_of(input.limits, [](const auto &lim) { return lim.first < lim.second; })) { + return false; + } + + return true; +} + +bool ShkrebkoMCalcOfIntegralRectTBB::PreProcessingImpl() { + local_input_ = GetInput(); + res_ = 0.0; + return true; +} + +bool ShkrebkoMCalcOfIntegralRectTBB::RunImpl() { + const std::size_t dim = local_input_.limits.size(); + + std::vector h(dim); + double cell_volume = 1.0; + std::size_t total_points = 1; + for (std::size_t i = 0; i < dim; ++i) { + const double left = local_input_.limits[i].first; + const double right = local_input_.limits[i].second; + const int steps = local_input_.n_steps[i]; + h[i] = (right - left) / static_cast(steps); + cell_volume *= h[i]; + total_points *= static_cast(steps); + } + + int num_threads = ppc::util::GetNumThreads(); + tbb::global_control global_limit(tbb::global_control::max_allowed_parallelism, num_threads); + + double total_sum = tbb::parallel_reduce(tbb::blocked_range(0, total_points), 0.0, + [&](const tbb::blocked_range &range, double partial_sum) { + return partial_sum + ComputeBlockSum(range.begin(), range.end(), h); + }, std::plus<>()); + + res_ = total_sum * cell_volume; + return true; +} + +bool ShkrebkoMCalcOfIntegralRectTBB::PostProcessingImpl() { + GetOutput() = res_; + return true; +} + +double ShkrebkoMCalcOfIntegralRectTBB::ComputeBlockSum(std::size_t start_idx, std::size_t end_idx, + const std::vector &h) const { + if (start_idx >= end_idx) { + return 0.0; + } + + const std::size_t dim = local_input_.limits.size(); + const auto &limits = local_input_.limits; + const auto &n_steps = local_input_.n_steps; + + std::vector indices(dim); + std::size_t temp = start_idx; + for (int idx = static_cast(dim) - 1; idx >= 0; --idx) { + { + indices[idx] = static_cast(temp % static_cast(n_steps[idx])); + temp /= static_cast(n_steps[idx]); + } + } + double block_sum = 0.0; + std::vector point(dim); + + for (std::size_t iter = 0; iter < (end_idx - start_idx); ++iter) { + for (std::size_t dim_idx = 0; dim_idx < dim; ++dim_idx) { + point[dim_idx] = limits[dim_idx].first + ((static_cast(indices[dim_idx]) + 0.5) * h[dim_idx]); + } + block_sum += local_input_.func(point); + + int level = static_cast(dim) - 1; + while (level >= 0) { + indices[level]++; + if (indices[level] < n_steps[level]) { + break; + } + indices[level] = 0; + level--; + } + } + + return block_sum; +} + +} // namespace shkrebko_m_calc_of_integral_rect diff --git a/tasks/shkrebko_m_calc_of_integral_rect/tests/functional/main.cpp b/tasks/shkrebko_m_calc_of_integral_rect/tests/functional/main.cpp index d0a743376..131ad370c 100644 --- a/tasks/shkrebko_m_calc_of_integral_rect/tests/functional/main.cpp +++ b/tasks/shkrebko_m_calc_of_integral_rect/tests/functional/main.cpp @@ -13,6 +13,7 @@ #include "shkrebko_m_calc_of_integral_rect/common/include/common.hpp" #include "shkrebko_m_calc_of_integral_rect/omp/include/ops_omp.hpp" #include "shkrebko_m_calc_of_integral_rect/seq/include/ops_seq.hpp" +#include "shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" @@ -79,6 +80,8 @@ const std::array kTestCases = { const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestCases, PPC_SETTINGS_shkrebko_m_calc_of_integral_rect), ppc::util::AddFuncTask( + kTestCases, PPC_SETTINGS_shkrebko_m_calc_of_integral_rect), + ppc::util::AddFuncTask( kTestCases, PPC_SETTINGS_shkrebko_m_calc_of_integral_rect)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); diff --git a/tasks/shkrebko_m_calc_of_integral_rect/tests/performance/main.cpp b/tasks/shkrebko_m_calc_of_integral_rect/tests/performance/main.cpp index ba60b07f8..3557ac16f 100644 --- a/tasks/shkrebko_m_calc_of_integral_rect/tests/performance/main.cpp +++ b/tasks/shkrebko_m_calc_of_integral_rect/tests/performance/main.cpp @@ -7,6 +7,7 @@ #include "shkrebko_m_calc_of_integral_rect/common/include/common.hpp" #include "shkrebko_m_calc_of_integral_rect/omp/include/ops_omp.hpp" #include "shkrebko_m_calc_of_integral_rect/seq/include/ops_seq.hpp" +#include "shkrebko_m_calc_of_integral_rect/tbb/include/ops_tbb.hpp" #include "util/include/perf_test_util.hpp" namespace shkrebko_m_calc_of_integral_rect { @@ -46,7 +47,8 @@ TEST_P(ShkrebkoMRunPerfTest, RunPerfModes) { namespace { const auto kAllPerfTasks = std::tuple_cat( ppc::util::MakeAllPerfTasks(PPC_SETTINGS_shkrebko_m_calc_of_integral_rect), - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_shkrebko_m_calc_of_integral_rect)); + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_shkrebko_m_calc_of_integral_rect), + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_shkrebko_m_calc_of_integral_rect)); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks);