GCC Code Coverage Report


Directory: ./
File: tasks/sabirov_s_monte_carlo/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 96 96 100.0%
Functions: 9 9 100.0%
Branches: 56 77 72.7%

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