|
| 1 | +#include "sabirov_s_monte_carlo/tbb/include/ops_tbb.hpp" |
| 2 | + |
| 3 | +#include <cstddef> |
| 4 | +#include <cstdint> |
| 5 | +#include <random> |
| 6 | +#include <vector> |
| 7 | + |
| 8 | +#include "oneapi/tbb/blocked_range.h" |
| 9 | +#include "oneapi/tbb/parallel_reduce.h" |
| 10 | +#include "sabirov_s_monte_carlo/common/include/common.hpp" |
| 11 | + |
| 12 | +namespace sabirov_s_monte_carlo { |
| 13 | + |
| 14 | +SabirovSMonteCarloTBB::SabirovSMonteCarloTBB(const InType &in) { |
| 15 | + SetTypeOfTask(GetStaticTypeOfTask()); |
| 16 | + GetInput() = in; |
| 17 | + GetOutput() = 0.0; |
| 18 | +} |
| 19 | + |
| 20 | +bool SabirovSMonteCarloTBB::ValidationImpl() { |
| 21 | + const auto &in = GetInput(); |
| 22 | + if (in.lower.size() != in.upper.size() || in.lower.empty()) { |
| 23 | + return false; |
| 24 | + } |
| 25 | + if (in.num_samples <= 0) { |
| 26 | + return false; |
| 27 | + } |
| 28 | + for (size_t i = 0; i < in.lower.size(); ++i) { |
| 29 | + if (in.lower[i] >= in.upper[i]) { |
| 30 | + return false; |
| 31 | + } |
| 32 | + } |
| 33 | + if (in.func_type < FuncType::kLinear || in.func_type > FuncType::kQuarticSum) { |
| 34 | + return false; |
| 35 | + } |
| 36 | + constexpr size_t kMaxDimensions = 10; |
| 37 | + return in.lower.size() <= kMaxDimensions; |
| 38 | +} |
| 39 | + |
| 40 | +bool SabirovSMonteCarloTBB::PreProcessingImpl() { |
| 41 | + const auto &in = GetInput(); |
| 42 | + lower_ = in.lower; |
| 43 | + upper_ = in.upper; |
| 44 | + num_samples_ = in.num_samples; |
| 45 | + func_type_ = in.func_type; |
| 46 | + GetOutput() = 0.0; |
| 47 | + return true; |
| 48 | +} |
| 49 | + |
| 50 | +bool SabirovSMonteCarloTBB::RunImpl() { |
| 51 | + const int dims = static_cast<int>(lower_.size()); |
| 52 | + |
| 53 | + std::vector<std::uniform_real_distribution<double>> dists; |
| 54 | + dists.reserve(static_cast<size_t>(dims)); |
| 55 | + for (int j = 0; j < dims; ++j) { |
| 56 | + dists.emplace_back(lower_[j], upper_[j]); |
| 57 | + } |
| 58 | + |
| 59 | + double volume = 1.0; |
| 60 | + for (int j = 0; j < dims; ++j) { |
| 61 | + volume *= (upper_[j] - lower_[j]); |
| 62 | + } |
| 63 | + |
| 64 | + const FuncType ftype = func_type_; |
| 65 | + const int n_samples = num_samples_; |
| 66 | + |
| 67 | + const double sum = tbb::parallel_reduce(tbb::blocked_range<int>(0, n_samples), 0.0, |
| 68 | + [&](const tbb::blocked_range<int> &r, double init) { |
| 69 | + double local = init; |
| 70 | + std::vector<double> point(static_cast<size_t>(dims)); |
| 71 | + std::seed_seq seed{static_cast<uint32_t>(r.begin()), static_cast<uint32_t>(r.end()), |
| 72 | + static_cast<uint32_t>(n_samples)}; |
| 73 | + std::mt19937 gen(seed); |
| 74 | + for (int i = r.begin(); i != r.end(); ++i) { |
| 75 | + for (int j = 0; j < dims; ++j) { |
| 76 | + point[static_cast<size_t>(j)] = dists[static_cast<size_t>(j)](gen); |
| 77 | + } |
| 78 | + local += detail::EvaluateAt(ftype, point); |
| 79 | + } |
| 80 | + return local; |
| 81 | + }, [](double a, double b) { return a + b; }); |
| 82 | + |
| 83 | + GetOutput() = volume * sum / static_cast<double>(num_samples_); |
| 84 | + return true; |
| 85 | +} |
| 86 | + |
| 87 | +bool SabirovSMonteCarloTBB::PostProcessingImpl() { |
| 88 | + return true; |
| 89 | +} |
| 90 | + |
| 91 | +} // namespace sabirov_s_monte_carlo |
0 commit comments