| 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 |