GCC Code Coverage Report


Directory: ./
File: tasks/klimenko_v_multistep_2d_parallel_sad/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 97 99 98.0%
Functions: 11 12 91.7%
Branches: 76 122 62.3%

Line Branch Exec Source
1 #include "klimenko_v_multistep_2d_parallel_sad/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <limits>
8 #include <utility>
9 #include <vector>
10
11 #include "klimenko_v_multistep_2d_parallel_sad/common/include/common.hpp"
12
13 namespace klimenko_v_multistep_2d_parallel_sad {
14
15
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 KlimenkoV2DParallelSadMPI::KlimenkoV2DParallelSadMPI(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 6 GetOutput() = OutType();
19
20
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank_);
21
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Comm_size(MPI_COMM_WORLD, &world_size_);
22 6 }
23
24 6 bool KlimenkoV2DParallelSadMPI::ValidationImpl() {
25
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (world_rank_ != 0) {
26 return true;
27 }
28
29 const auto &in = GetInput();
30
5/10
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
3 return in.func != nullptr && in.x_min < in.x_max && in.y_min < in.y_max && in.epsilon > 0.0 && in.r_param > 1.0 &&
31
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 in.max_iterations > 0;
32 }
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 bool KlimenkoV2DParallelSadMPI::PreProcessingImpl() {
35 regions_.clear();
36
37
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (world_rank_ == 0) {
38 const auto &in = GetInput();
39
40 3 Region r{};
41 3 r.x_min = in.x_min;
42 3 r.x_max = in.x_max;
43 3 r.y_min = in.y_min;
44 3 r.y_max = in.y_max;
45 3 double xc = 0.5 * (r.x_min + r.x_max);
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 double yc = 0.5 * (r.y_min + r.y_max);
47 3 r.f_center = in.func(xc, yc);
48 r.characteristic = 0.0;
49
50 3 regions_.push_back(r);
51 3 epsilon_ = in.epsilon;
52 }
53
54 6 MPI_Bcast(&epsilon_, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
55 6 return true;
56 }
57
58 282 double KlimenkoV2DParallelSadMPI::ComputeCharacteristic(const Region &r) {
59 const auto &in = GetInput();
60
61 282 double dx = r.x_max - r.x_min;
62 282 double dy = r.y_max - r.y_min;
63
64 282 return (-r.f_center) + (in.r_param * std::sqrt((dx * dx) + (dy * dy)));
65 ;
66 }
67
68 std::pair<Region, Region> KlimenkoV2DParallelSadMPI::SplitRegion(const Region &r) {
69 45 Region r1 = r;
70 Region r2 = r;
71
72
2/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
45 if ((r.x_max - r.x_min) >= (r.y_max - r.y_min)) {
73 18 double xm = 0.5 * (r.x_min + r.x_max);
74 r1.x_max = xm;
75 r2.x_min = xm;
76 } else {
77 27 double ym = 0.5 * (r.y_min + r.y_max);
78 r1.y_max = ym;
79 r2.y_min = ym;
80 }
81
82 return {r1, r2};
83 }
84
85 6 bool KlimenkoV2DParallelSadMPI::RunImpl() {
86 const auto &in = GetInput();
87
88
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 6 times.
96 for (int iter = 0; iter < in.max_iterations; ++iter) {
89 90 const Region local_best = FindLocalBestRegion();
90 90 const double local_char = ComputeCharacteristic(local_best);
91
92 90 const Region best_region = FindGlobalBestRegion(local_best, local_char);
93
94 90 SplitBestRegion(best_region);
95
96
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 if (CheckStopCondition()) {
97 break;
98 }
99 }
100 6 return true;
101 }
102
103 6 bool KlimenkoV2DParallelSadMPI::PostProcessingImpl() {
104 auto &out = GetOutput();
105
106 6 double func_min = 0.0;
107 6 double x_opt = 0.0;
108 6 double y_opt = 0.0;
109
110
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (world_rank_ == 0) {
111 double best_val = std::numeric_limits<double>::max();
112
113
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3 times.
51 for (const auto &r : regions_) {
114
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 39 times.
48 if (r.f_center < best_val) {
115 best_val = r.f_center;
116 9 func_min = r.f_center;
117 9 x_opt = 0.5 * (r.x_min + r.x_max);
118 9 y_opt = 0.5 * (r.y_min + r.y_max);
119 }
120 }
121 }
122
123 6 MPI_Bcast(&func_min, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
124 6 MPI_Bcast(&x_opt, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
125 6 MPI_Bcast(&y_opt, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
126
127 6 out.func_min = func_min;
128 6 out.x_opt = x_opt;
129 6 out.y_opt = y_opt;
130
131 6 return true;
132 }
133
134 90 Region KlimenkoV2DParallelSadMPI::FindLocalBestRegion() {
135 90 Region best{};
136 double best_char = -std::numeric_limits<double>::infinity();
137
138
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 90 times.
282 for (auto i = static_cast<std::size_t>(world_rank_); i < regions_.size();
139 192 i += static_cast<std::size_t>(world_size_)) {
140 192 const double ch = ComputeCharacteristic(regions_[i]);
141
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 138 times.
192 if (ch > best_char) {
142 best_char = ch;
143 54 best = regions_[i];
144 }
145 }
146 90 return best;
147 }
148
149 90 Region KlimenkoV2DParallelSadMPI::FindGlobalBestRegion(const Region &local_best, double local_char) const {
150 struct {
151 double value;
152 int rank;
153 90 } local_pair{.value = local_char, .rank = world_rank_}, global_pair{};
154
155 90 MPI_Reduce(&local_pair, &global_pair, 1, MPI_DOUBLE_INT, MPI_MAXLOC, 0, MPI_COMM_WORLD);
156
157 90 Region best{};
158
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 45 times.
90 if (world_rank_ == global_pair.rank) {
159 45 best = local_best;
160 }
161
162 90 MPI_Bcast(&best, static_cast<int>(sizeof(Region)), MPI_BYTE, global_pair.rank, MPI_COMM_WORLD);
163 90 return best;
164 }
165
166 90 void KlimenkoV2DParallelSadMPI::SplitBestRegion(const Region &best_region) {
167
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 45 times.
90 if (world_rank_ != 0) {
168 45 return;
169 }
170
171 const auto split = SplitRegion(best_region);
172
173 45 std::erase_if(regions_, [&](const Region &r) {
174
32/48
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 11 times.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 7 times.
✓ Branch 20 taken 3 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 4 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 5 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 5 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 40 times.
✓ Branch 43 taken 225 times.
✓ Branch 44 taken 32 times.
✓ Branch 45 taken 8 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 32 times.
321 return r.x_min == best_region.x_min && r.x_max == best_region.x_max && r.y_min == best_region.y_min &&
175
5/16
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
45 r.y_max == best_region.y_max;
176 });
177
178 90 auto eval = [&](Region &r) {
179 90 const double xc = 0.5 * (r.x_min + r.x_max);
180 90 const double yc = 0.5 * (r.y_min + r.y_max);
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 r.f_center = GetInput().func(xc, yc);
182 135 };
183
184 45 Region r1 = split.first;
185 45 Region r2 = split.second;
186
187 45 eval(r1);
188 45 eval(r2);
189
190 45 regions_.push_back(r1);
191 45 regions_.push_back(r2);
192 }
193
194 90 bool KlimenkoV2DParallelSadMPI::CheckStopCondition() const {
195 90 int stop_flag = 0;
196
197
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
90 if (world_rank_ == 0 && !regions_.empty()) {
198 const auto &last = regions_.back();
199 45 const double dx = last.x_max - last.x_min;
200 45 const double dy = last.y_max - last.y_min;
201
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90 stop_flag = (dx < epsilon_ && dy < epsilon_) ? 1 : 0;
202 }
203
204 90 MPI_Bcast(&stop_flag, 1, MPI_INT, 0, MPI_COMM_WORLD);
205 90 return stop_flag == 1;
206 }
207
208 } // namespace klimenko_v_multistep_2d_parallel_sad
209