| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "sabirov_s_monte_carlo/all/include/ops_all.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | #include <omp.h> | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | #include <array> | ||
| 8 | #include <cmath> | ||
| 9 | #include <cstddef> | ||
| 10 | #include <random> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "sabirov_s_monte_carlo/common/include/common.hpp" | ||
| 14 | #include "util/include/util.hpp" | ||
| 15 | |||
| 16 | namespace sabirov_s_monte_carlo { | ||
| 17 | |||
| 18 | namespace { | ||
| 19 | |||
| 20 | double EvalLinear(const std::vector<double> &point) { | ||
| 21 | double s = 0.0; | ||
| 22 |
2/2✓ Branch 0 taken 110000 times.
✓ Branch 1 taken 60000 times.
|
170000 | for (double x : point) { |
| 23 | 110000 | s += x; | |
| 24 | } | ||
| 25 | return s; | ||
| 26 | } | ||
| 27 | |||
| 28 | double EvalSumCubes(const std::vector<double> &point) { | ||
| 29 | double s = 0.0; | ||
| 30 |
2/2✓ Branch 0 taken 110000 times.
✓ Branch 1 taken 60000 times.
|
170000 | for (double x : point) { |
| 31 | 110000 | s += x * x * x; | |
| 32 | } | ||
| 33 | return s; | ||
| 34 | } | ||
| 35 | |||
| 36 | double EvalCosProduct(const std::vector<double> &point) { | ||
| 37 | double p = 1.0; | ||
| 38 |
2/2✓ Branch 0 taken 110000 times.
✓ Branch 1 taken 60000 times.
|
170000 | for (double x : point) { |
| 39 | 110000 | p *= std::cos(x); | |
| 40 | } | ||
| 41 | return p; | ||
| 42 | } | ||
| 43 | |||
| 44 | double EvalExpNeg(const std::vector<double> &point) { | ||
| 45 | double s = 0.0; | ||
| 46 |
2/2✓ Branch 0 taken 110000 times.
✓ Branch 1 taken 60000 times.
|
170000 | for (double x : point) { |
| 47 | 110000 | s += x; | |
| 48 | } | ||
| 49 | 60000 | return std::exp(-s); | |
| 50 | } | ||
| 51 | |||
| 52 | double EvalMixedPoly(const std::vector<double> &point) { | ||
| 53 | double s = 0.0; | ||
| 54 |
2/2✓ Branch 0 taken 310000 times.
✓ Branch 1 taken 110000 times.
|
420000 | for (double x : point) { |
| 55 | 310000 | s += (x * x) + x; | |
| 56 | } | ||
| 57 | return s; | ||
| 58 | } | ||
| 59 | |||
| 60 | double EvalSinSum(const std::vector<double> &point) { | ||
| 61 | double s = 0.0; | ||
| 62 |
2/2✓ Branch 0 taken 10000 times.
✓ Branch 1 taken 10000 times.
|
20000 | for (double x : point) { |
| 63 | 10000 | s += std::sin(x); | |
| 64 | } | ||
| 65 | return s; | ||
| 66 | } | ||
| 67 | |||
| 68 | double EvalSqrtSum(const std::vector<double> &point) { | ||
| 69 | double s = 0.0; | ||
| 70 |
2/2✓ Branch 0 taken 10000 times.
✓ Branch 1 taken 10000 times.
|
20000 | for (double x : point) { |
| 71 | 10000 | s += std::sqrt(x); | |
| 72 | } | ||
| 73 | return s; | ||
| 74 | } | ||
| 75 | |||
| 76 | double EvalQuarticSum(const std::vector<double> &point) { | ||
| 77 | double s = 0.0; | ||
| 78 |
2/2✓ Branch 0 taken 100000 times.
✓ Branch 1 taken 50000 times.
|
150000 | for (double x : point) { |
| 79 | 100000 | s += x * x * x * x; | |
| 80 | } | ||
| 81 | return s; | ||
| 82 | } | ||
| 83 | |||
| 84 | 420000 | double EvaluateAt(FuncType func_type, const std::vector<double> &point) { | |
| 85 |
8/9✓ Branch 0 taken 60000 times.
✓ Branch 1 taken 60000 times.
✓ Branch 2 taken 60000 times.
✓ Branch 3 taken 60000 times.
✓ Branch 4 taken 110000 times.
✓ Branch 5 taken 10000 times.
✓ Branch 6 taken 10000 times.
✓ Branch 7 taken 50000 times.
✗ Branch 8 not taken.
|
420000 | switch (func_type) { |
| 86 | case FuncType::kLinear: | ||
| 87 | return EvalLinear(point); | ||
| 88 | case FuncType::kSumCubes: | ||
| 89 | return EvalSumCubes(point); | ||
| 90 | case FuncType::kCosProduct: | ||
| 91 | return EvalCosProduct(point); | ||
| 92 | case FuncType::kExpNeg: | ||
| 93 | 60000 | return EvalExpNeg(point); | |
| 94 | case FuncType::kMixedPoly: | ||
| 95 | return EvalMixedPoly(point); | ||
| 96 | case FuncType::kSinSum: | ||
| 97 | return EvalSinSum(point); | ||
| 98 | case FuncType::kSqrtSum: | ||
| 99 | return EvalSqrtSum(point); | ||
| 100 | case FuncType::kQuarticSum: | ||
| 101 | return EvalQuarticSum(point); | ||
| 102 | default: | ||
| 103 | return 0.0; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | void FillScatterCounts(int num_samples, int size, std::vector<int> *counts) { | ||
| 108 | 13 | const int base = num_samples / size; | |
| 109 | 13 | const int rem = num_samples % size; | |
| 110 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13 times.
|
39 | for (int rk = 0; rk < size; ++rk) { |
| 111 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
52 | (*counts)[static_cast<size_t>(rk)] = base + (rk < rem ? 1 : 0); |
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | 13 | void SendParamsToNonRoot(int size, const std::vector<double> &lower, const std::vector<double> &upper, int num_samples, | |
| 116 | FuncType func_type) { | ||
| 117 | 13 | const int dims_send = static_cast<int>(lower.size()); | |
| 118 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
|
26 | for (int dest = 1; dest < size; ++dest) { |
| 119 | 13 | std::array<int, 3> head = {dims_send, num_samples, static_cast<int>(func_type)}; | |
| 120 | 13 | MPI_Send(head.data(), 3, MPI_INT, dest, 0, MPI_COMM_WORLD); | |
| 121 | 13 | MPI_Send(lower.data(), dims_send, MPI_DOUBLE, dest, 1, MPI_COMM_WORLD); | |
| 122 | 13 | MPI_Send(upper.data(), dims_send, MPI_DOUBLE, dest, 2, MPI_COMM_WORLD); | |
| 123 | } | ||
| 124 | 13 | } | |
| 125 | |||
| 126 | 13 | void RecvParamsFromRoot(std::vector<double> *lower, std::vector<double> *upper, int *num_samples, FuncType *func_type) { | |
| 127 | 13 | std::array<int, 3> head{}; | |
| 128 | 13 | MPI_Recv(head.data(), 3, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | |
| 129 | 13 | const int rdims = head[0]; | |
| 130 | 13 | *num_samples = head[1]; | |
| 131 | 13 | *func_type = static_cast<FuncType>(head[2]); | |
| 132 | 13 | lower->resize(static_cast<size_t>(rdims)); | |
| 133 | 13 | upper->resize(static_cast<size_t>(rdims)); | |
| 134 | 13 | MPI_Recv(lower->data(), rdims, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | |
| 135 | 13 | MPI_Recv(upper->data(), rdims, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | |
| 136 | 13 | } | |
| 137 | |||
| 138 | double HyperrectangleVolume(const std::vector<double> &lower, const std::vector<double> &upper) { | ||
| 139 | double volume = 1.0; | ||
| 140 | 26 | const int dims = static_cast<int>(lower.size()); | |
| 141 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 26 times.
|
66 | for (int vi = 0; vi < dims; ++vi) { |
| 142 | 40 | volume *= (upper[static_cast<size_t>(vi)] - lower[static_cast<size_t>(vi)]); | |
| 143 | } | ||
| 144 | return volume; | ||
| 145 | } | ||
| 146 | |||
| 147 | 26 | double ParallelLocalSum(const std::vector<double> &lower, const std::vector<double> &upper, int local_n, | |
| 148 | FuncType ftype) { | ||
| 149 | 26 | const int dims = static_cast<int>(lower.size()); | |
| 150 | const std::vector<double> *const plower = &lower; | ||
| 151 | const std::vector<double> *const pupper = &upper; | ||
| 152 | const FuncType copy_ftype = ftype; | ||
| 153 | const int ln = local_n; | ||
| 154 | double sum = 0.0; | ||
| 155 | |||
| 156 | 26 | #pragma omp parallel default(none) shared(plower, pupper, copy_ftype, dims, ln) reduction(+ : sum) | |
| 157 | { | ||
| 158 | std::random_device rd; | ||
| 159 | std::mt19937 gen(rd()); | ||
| 160 | std::vector<std::uniform_real_distribution<double>> dists; | ||
| 161 | dists.reserve(static_cast<size_t>(dims)); | ||
| 162 | for (int wi = 0; wi < dims; ++wi) { | ||
| 163 | dists.emplace_back((*plower)[static_cast<size_t>(wi)], (*pupper)[static_cast<size_t>(wi)]); | ||
| 164 | } | ||
| 165 | std::vector<double> point(static_cast<size_t>(dims)); | ||
| 166 | |||
| 167 | #pragma omp for schedule(static) | ||
| 168 | for (int si = 0; si < ln; ++si) { | ||
| 169 | for (int sj = 0; sj < dims; ++sj) { | ||
| 170 | point[static_cast<size_t>(sj)] = dists[static_cast<size_t>(sj)](gen); | ||
| 171 | } | ||
| 172 | sum += EvaluateAt(copy_ftype, point); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | 26 | return sum; | |
| 176 | } | ||
| 177 | |||
| 178 | } // namespace | ||
| 179 | |||
| 180 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | SabirovSMonteCarloALL::SabirovSMonteCarloALL(const InType &in) { |
| 181 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 182 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | GetInput() = in; |
| 183 | 26 | GetOutput() = 0.0; | |
| 184 | 26 | } | |
| 185 | |||
| 186 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | bool SabirovSMonteCarloALL::ValidationImpl() { |
| 187 | const auto &in = GetInput(); | ||
| 188 |
2/4✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
|
26 | if (in.lower.size() != in.upper.size() || in.lower.empty()) { |
| 189 | return false; | ||
| 190 | } | ||
| 191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | if (in.num_samples <= 0) { |
| 192 | return false; | ||
| 193 | } | ||
| 194 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 26 times.
|
66 | for (size_t i = 0; i < in.lower.size(); ++i) { |
| 195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (in.lower[i] >= in.upper[i]) { |
| 196 | return false; | ||
| 197 | } | ||
| 198 | } | ||
| 199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | if (in.func_type < FuncType::kLinear || in.func_type > FuncType::kQuarticSum) { |
| 200 | return false; | ||
| 201 | } | ||
| 202 | constexpr size_t kMaxDimensions = 10; | ||
| 203 | 26 | return in.lower.size() <= kMaxDimensions; | |
| 204 | } | ||
| 205 | |||
| 206 | 26 | bool SabirovSMonteCarloALL::PreProcessingImpl() { | |
| 207 | const auto &in = GetInput(); | ||
| 208 | 26 | lower_ = in.lower; | |
| 209 | 26 | upper_ = in.upper; | |
| 210 | 26 | num_samples_ = in.num_samples; | |
| 211 | 26 | func_type_ = in.func_type; | |
| 212 | 26 | GetOutput() = 0.0; | |
| 213 | 26 | return true; | |
| 214 | } | ||
| 215 | |||
| 216 | 26 | bool SabirovSMonteCarloALL::RunImpl() { | |
| 217 | 26 | omp_set_num_threads(std::max(1, ppc::util::GetNumThreads())); | |
| 218 | |||
| 219 | 26 | int rank = 0; | |
| 220 | 26 | int size = 1; | |
| 221 | 26 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 222 | 26 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 223 | |||
| 224 | 26 | std::vector<int> counts(static_cast<size_t>(size)); | |
| 225 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
|
26 | if (rank == 0) { |
| 226 | 13 | FillScatterCounts(num_samples_, size, &counts); | |
| 227 | } | ||
| 228 | |||
| 229 | 26 | int local_n = 0; | |
| 230 |
1/4✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
26 | std::vector<int> scounts(static_cast<size_t>(size), 1); |
| 231 |
1/4✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
26 | std::vector<int> displs(static_cast<size_t>(size)); |
| 232 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 26 times.
|
78 | for (int di = 0; di < size; ++di) { |
| 233 | 52 | displs[static_cast<size_t>(di)] = di; | |
| 234 | } | ||
| 235 | |||
| 236 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
|
26 | const int *scatter_send = (rank == 0) ? counts.data() : nullptr; |
| 237 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | MPI_Scatterv(scatter_send, scounts.data(), displs.data(), MPI_INT, &local_n, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 238 | |||
| 239 | 26 | int global_n = num_samples_; | |
| 240 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
|
26 | if (rank == 0) { |
| 241 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | SendParamsToNonRoot(size, lower_, upper_, num_samples_, func_type_); |
| 242 | } else { | ||
| 243 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | RecvParamsFromRoot(&lower_, &upper_, &num_samples_, &func_type_); |
| 244 | 13 | global_n = num_samples_; | |
| 245 | } | ||
| 246 | |||
| 247 | const double volume = HyperrectangleVolume(lower_, upper_); | ||
| 248 | 26 | double sum = ParallelLocalSum(lower_, upper_, local_n, func_type_); | |
| 249 | |||
| 250 | 26 | double global_sum = 0.0; | |
| 251 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | MPI_Allreduce(&sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); |
| 252 | |||
| 253 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | GetOutput() = volume * global_sum / static_cast<double>(global_n); |
| 254 | 26 | return true; | |
| 255 | } | ||
| 256 | |||
| 257 | 26 | bool SabirovSMonteCarloALL::PostProcessingImpl() { | |
| 258 | 26 | return true; | |
| 259 | } | ||
| 260 | |||
| 261 | } // namespace sabirov_s_monte_carlo | ||
| 262 |