| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "luchnikov_e_graham_cov_hall_constr/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "luchnikov_e_graham_cov_hall_constr/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace luchnikov_e_graham_cov_hall_constr { | ||
| 14 | |||
| 15 | namespace { | ||
| 16 | |||
| 17 | constexpr double kEpsilon = 1e-9; | ||
| 18 | constexpr int kMinPointsPerProcess = 10; | ||
| 19 | |||
| 20 | constexpr int kTagSize = 0; | ||
| 21 | constexpr int kTagX = 1; | ||
| 22 | constexpr int kTagY = 2; | ||
| 23 | |||
| 24 | int CalculateLocalOrSendcount(int index, int active_procs, int base_count, int remainder) { | ||
| 25 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (index < active_procs) { |
| 26 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
|
22 | return base_count + (index < remainder ? 1 : 0); |
| 27 | } | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | int ComputeOrientation(const Point &p, const Point &q, const Point &r) { | ||
| 32 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 147 times.
|
352 | const double value = ((q.y - p.y) * (r.x - q.x)) - ((q.x - p.x) * (r.y - q.y)); |
| 33 | |||
| 34 |
6/6✓ Branch 0 taken 53 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 160 times.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 147 times.
|
1048 | if (std::abs(value) < kEpsilon) { |
| 35 | return 0; | ||
| 36 | } | ||
| 37 |
4/4✓ Branch 0 taken 313 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 126 times.
|
803 | return (value > 0) ? 1 : 2; |
| 38 | } | ||
| 39 | |||
| 40 | double ComputeDistanceSquared(const Point &a, const Point &b) { | ||
| 41 | 53 | return ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y)); | |
| 42 | } | ||
| 43 | |||
| 44 | 25 | std::size_t FindMinPointIndex(const std::vector<Point> &points) { | |
| 45 | std::size_t min_index = 0; | ||
| 46 |
2/2✓ Branch 0 taken 207 times.
✓ Branch 1 taken 25 times.
|
232 | for (std::size_t i = 1; i < points.size(); ++i) { |
| 47 |
4/4✓ Branch 0 taken 192 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 166 times.
|
207 | if (points[i].y < points[min_index].y || |
| 48 |
4/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 166 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 23 times.
|
192 | (std::abs(points[i].y - points[min_index].y) < kEpsilon && points[i].x < points[min_index].x)) { |
| 49 | min_index = i; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | 25 | return min_index; | |
| 53 | } | ||
| 54 | |||
| 55 | 25 | void FilterCollinearPoints(std::vector<Point> &points, const Point &pivot) { | |
| 56 | std::size_t unique_count = 1; | ||
| 57 |
2/2✓ Branch 0 taken 172 times.
✓ Branch 1 taken 25 times.
|
197 | for (std::size_t i = 1; i < points.size(); ++i) { |
| 58 |
2/2✓ Branch 0 taken 182 times.
✓ Branch 1 taken 25 times.
|
207 | while (i + 1 < points.size() && ComputeOrientation(pivot, points[i], points[i + 1]) == 0) { |
| 59 | ++i; | ||
| 60 | } | ||
| 61 | 172 | points[unique_count++] = points[i]; | |
| 62 | } | ||
| 63 | 25 | points.resize(unique_count); | |
| 64 | 25 | } | |
| 65 | |||
| 66 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | void BuildConvexHull(const std::vector<Point> &points, std::vector<Point> &hull) { |
| 67 | hull.clear(); | ||
| 68 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
|
25 | if (points.size() < 3) { |
| 69 | 4 | hull = points; | |
| 70 | 4 | return; | |
| 71 | } | ||
| 72 | |||
| 73 | 21 | hull.reserve(points.size()); | |
| 74 | hull.push_back(points[0]); | ||
| 75 | hull.push_back(points[1]); | ||
| 76 | hull.push_back(points[2]); | ||
| 77 | |||
| 78 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 21 times.
|
147 | for (std::size_t i = 3; i < points.size(); ++i) { |
| 79 |
1/2✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
|
170 | while (hull.size() >= 2 && ComputeOrientation(hull[hull.size() - 2], hull[hull.size() - 1], points[i]) != 2) { |
| 80 | hull.pop_back(); | ||
| 81 | } | ||
| 82 | hull.push_back(points[i]); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace | ||
| 87 | |||
| 88 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | LuchnikovEGrahamConvexHullMPI::LuchnikovEGrahamConvexHullMPI(const InType &in) { |
| 89 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 90 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | GetInput() = in; |
| 91 | 32 | GetOutput() = OutType{}; | |
| 92 | 32 | } | |
| 93 | |||
| 94 | 32 | bool LuchnikovEGrahamConvexHullMPI::ValidationImpl() { | |
| 95 | 32 | return GetInput().size() >= 3; | |
| 96 | } | ||
| 97 | |||
| 98 | 32 | bool LuchnikovEGrahamConvexHullMPI::PreProcessingImpl() { | |
| 99 | 32 | return true; | |
| 100 | } | ||
| 101 | |||
| 102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | std::vector<Point> LuchnikovEGrahamConvexHullMPI::GrahamScan(const std::vector<Point> &input_points) { |
| 103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (input_points.size() < 3) { |
| 104 | ✗ | return input_points; | |
| 105 | } | ||
| 106 | |||
| 107 | 25 | std::vector<Point> points{input_points}; | |
| 108 | |||
| 109 | 25 | const std::size_t min_index = FindMinPointIndex(points); | |
| 110 | std::swap(points[0], points[min_index]); | ||
| 111 | 25 | const Point pivot = points[0]; | |
| 112 | |||
| 113 | 721 | std::sort(points.begin() + 1, points.end(), [&pivot](const Point &a, const Point &b) { | |
| 114 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 643 times.
|
696 | const int orient = ComputeOrientation(pivot, a, b); |
| 115 | if (orient == 0) { | ||
| 116 | const double dist_a = ComputeDistanceSquared(a, pivot); | ||
| 117 | const double dist_b = ComputeDistanceSquared(b, pivot); | ||
| 118 | 53 | return dist_a < dist_b; | |
| 119 | } | ||
| 120 | 643 | return orient == 2; | |
| 121 | }); | ||
| 122 | |||
| 123 |
1/2✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
|
25 | FilterCollinearPoints(points, pivot); |
| 124 | |||
| 125 | 25 | std::vector<Point> hull; | |
| 126 |
1/2✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
|
25 | BuildConvexHull(points, hull); |
| 127 | |||
| 128 | return hull; | ||
| 129 | } | ||
| 130 | |||
| 131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | std::vector<Point> LuchnikovEGrahamConvexHullMPI::MergeHulls(const std::vector<Point> &hull_left, |
| 132 | const std::vector<Point> &hull_right) { | ||
| 133 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (hull_left.empty()) { |
| 134 | ✗ | return hull_right; | |
| 135 | } | ||
| 136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (hull_right.empty()) { |
| 137 | ✗ | return hull_left; | |
| 138 | } | ||
| 139 | |||
| 140 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<Point> merged; |
| 141 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | merged.reserve(hull_left.size() + hull_right.size()); |
| 142 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | merged.insert(merged.end(), hull_left.begin(), hull_left.end()); |
| 143 | 6 | merged.insert(merged.end(), hull_right.begin(), hull_right.end()); | |
| 144 | |||
| 145 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | return GrahamScan(merged); |
| 146 | } | ||
| 147 | |||
| 148 | ✗ | int LuchnikovEGrahamConvexHullMPI::CalculateOptimalActiveProcs(int points_count, int world_size) { | |
| 149 | ✗ | int active_procs = world_size; | |
| 150 | |||
| 151 |
6/12✓ Branch 0 taken 32 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
64 | while (active_procs > 1 && points_count / active_procs < kMinPointsPerProcess) { |
| 152 | 26 | --active_procs; | |
| 153 | } | ||
| 154 | |||
| 155 |
5/12✓ Branch 0 taken 6 times.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
38 | while (active_procs > 1 && points_count / active_procs < 3) { |
| 156 | ✗ | --active_procs; | |
| 157 | } | ||
| 158 | |||
| 159 | ✗ | return std::max(active_procs, 1); | |
| 160 | } | ||
| 161 | |||
| 162 | 6 | std::vector<Point> LuchnikovEGrahamConvexHullMPI::PrepareAndDistributeData(int world_rank, int world_size, | |
| 163 | int &active_procs_out) { | ||
| 164 | 6 | int total_points = 0; | |
| 165 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (world_rank == 0) { |
| 166 | 3 | total_points = static_cast<int>(GetInput().size()); | |
| 167 | } | ||
| 168 | |||
| 169 | 6 | MPI_Bcast(&total_points, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 170 | |||
| 171 | 6 | const int active_procs = CalculateOptimalActiveProcs(total_points, world_size); | |
| 172 | 6 | active_procs_out = active_procs; | |
| 173 | |||
| 174 | const bool is_active = world_rank < active_procs; | ||
| 175 | |||
| 176 | 6 | const int base_count = total_points / active_procs; | |
| 177 | 6 | const int remainder = total_points % active_procs; | |
| 178 | |||
| 179 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | const int local_count = is_active ? CalculateLocalOrSendcount(world_rank, active_procs, base_count, remainder) : 0; |
| 180 | |||
| 181 | 6 | std::vector<int> sendcounts(world_size, 0); | |
| 182 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<int> displs(world_size, 0); |
| 183 | |||
| 184 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (world_rank == 0) { |
| 185 | int offset = 0; | ||
| 186 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | for (int i = 0; i < world_size; ++i) { |
| 187 | 6 | sendcounts[i] = CalculateLocalOrSendcount(i, active_procs, base_count, remainder); | |
| 188 | 6 | displs[i] = offset; | |
| 189 | 6 | offset += sendcounts[i]; | |
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Bcast(sendcounts.data(), world_size, MPI_INT, 0, MPI_COMM_WORLD); |
| 194 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Bcast(displs.data(), world_size, MPI_INT, 0, MPI_COMM_WORLD); |
| 195 | |||
| 196 | 6 | std::vector<double> all_x; | |
| 197 | 6 | std::vector<double> all_y; | |
| 198 | |||
| 199 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (world_rank == 0) { |
| 200 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | all_x.resize(total_points); |
| 201 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | all_y.resize(total_points); |
| 202 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 3 times.
|
78 | for (int i = 0; i < total_points; ++i) { |
| 203 | 75 | all_x[i] = GetInput()[static_cast<std::size_t>(i)].x; | |
| 204 | 75 | all_y[i] = GetInput()[static_cast<std::size_t>(i)].y; | |
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> local_x(static_cast<std::size_t>(local_count)); |
| 209 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> local_y(static_cast<std::size_t>(local_count)); |
| 210 | |||
| 211 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (local_count > 0) { |
| 212 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Scatterv(all_x.data(), sendcounts.data(), displs.data(), MPI_DOUBLE, local_x.data(), local_count, MPI_DOUBLE, 0, |
| 213 | MPI_COMM_WORLD); | ||
| 214 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Scatterv(all_y.data(), sendcounts.data(), displs.data(), MPI_DOUBLE, local_y.data(), local_count, MPI_DOUBLE, 0, |
| 215 | MPI_COMM_WORLD); | ||
| 216 | } | ||
| 217 | |||
| 218 | 6 | std::vector<Point> local_points; | |
| 219 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | local_points.reserve(static_cast<std::size_t>(local_count)); |
| 220 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 6 times.
|
81 | for (int i = 0; i < local_count; ++i) { |
| 221 |
1/2✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
|
75 | local_points.emplace_back(local_x[i], local_y[i]); |
| 222 | } | ||
| 223 | |||
| 224 | 6 | return local_points; | |
| 225 | } | ||
| 226 | |||
| 227 | 6 | std::vector<Point> LuchnikovEGrahamConvexHullMPI::MergeHullsBinaryTree(int world_rank, | |
| 228 | const std::vector<Point> &local_hull, | ||
| 229 | int active_procs) { | ||
| 230 | 6 | std::vector<Point> current_hull = local_hull; | |
| 231 | |||
| 232 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | for (int step = 1; step < active_procs; step <<= 1) { |
| 233 | 6 | const int partner = world_rank ^ step; | |
| 234 | |||
| 235 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (world_rank < active_procs && partner < active_procs) { |
| 236 | 6 | int my_size = static_cast<int>(current_hull.size()); | |
| 237 | 6 | int partner_size = 0; | |
| 238 | |||
| 239 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Sendrecv(&my_size, 1, MPI_INT, partner, kTagSize, &partner_size, 1, MPI_INT, partner, kTagSize, |
| 240 | MPI_COMM_WORLD, MPI_STATUS_IGNORE); | ||
| 241 | |||
| 242 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> my_x(my_size); |
| 243 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> my_y(my_size); |
| 244 | |||
| 245 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 6 times.
|
51 | for (int i = 0; i < my_size; ++i) { |
| 246 | 45 | my_x[i] = current_hull[static_cast<std::size_t>(i)].x; | |
| 247 | 45 | my_y[i] = current_hull[static_cast<std::size_t>(i)].y; | |
| 248 | } | ||
| 249 | |||
| 250 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> remote_x(partner_size); |
| 251 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> remote_y(partner_size); |
| 252 | |||
| 253 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Sendrecv(my_x.data(), my_size, MPI_DOUBLE, partner, kTagX, remote_x.data(), partner_size, MPI_DOUBLE, partner, |
| 254 | kTagX, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | ||
| 255 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Sendrecv(my_y.data(), my_size, MPI_DOUBLE, partner, kTagY, remote_y.data(), partner_size, MPI_DOUBLE, partner, |
| 256 | kTagY, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | ||
| 257 | |||
| 258 | 6 | std::vector<Point> remote_hull; | |
| 259 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | remote_hull.reserve(static_cast<std::size_t>(partner_size)); |
| 260 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 6 times.
|
51 | for (int i = 0; i < partner_size; ++i) { |
| 261 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | remote_hull.emplace_back(remote_x[i], remote_y[i]); |
| 262 | } | ||
| 263 | |||
| 264 |
2/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
12 | current_hull = MergeHulls(current_hull, remote_hull); |
| 265 | } | ||
| 266 | |||
| 267 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Barrier(MPI_COMM_WORLD); |
| 268 | } | ||
| 269 | |||
| 270 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
12 | return (world_rank < active_procs) ? current_hull : std::vector<Point>{}; |
| 271 | } | ||
| 272 | |||
| 273 | 32 | std::vector<Point> LuchnikovEGrahamConvexHullMPI::BroadcastFinalResult(int world_rank, | |
| 274 | const std::vector<Point> &root_hull) { | ||
| 275 | 32 | int hull_size = 0; | |
| 276 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 277 | 16 | hull_size = static_cast<int>(root_hull.size()); | |
| 278 | } | ||
| 279 | |||
| 280 | 32 | MPI_Bcast(&hull_size, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 281 | |||
| 282 | 32 | std::vector<Point> result; | |
| 283 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | result.reserve(static_cast<std::size_t>(hull_size)); |
| 284 | |||
| 285 |
1/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32 | std::vector<double> x(static_cast<std::size_t>(hull_size)); |
| 286 |
1/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32 | std::vector<double> y(static_cast<std::size_t>(hull_size)); |
| 287 | |||
| 288 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 289 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 16 times.
|
92 | for (int i = 0; i < hull_size; ++i) { |
| 290 | 76 | x[i] = root_hull[static_cast<std::size_t>(i)].x; | |
| 291 | 76 | y[i] = root_hull[static_cast<std::size_t>(i)].y; | |
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Bcast(x.data(), hull_size, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 296 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Bcast(y.data(), hull_size, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 297 | |||
| 298 |
2/2✓ Branch 0 taken 152 times.
✓ Branch 1 taken 32 times.
|
184 | for (int i = 0; i < hull_size; ++i) { |
| 299 |
1/2✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
|
152 | result.emplace_back(x[i], y[i]); |
| 300 | } | ||
| 301 | |||
| 302 | 32 | return result; | |
| 303 | } | ||
| 304 | |||
| 305 | 32 | bool LuchnikovEGrahamConvexHullMPI::RunImpl() { | |
| 306 | 32 | int world_size = 0; | |
| 307 | 32 | int world_rank = 0; | |
| 308 | |||
| 309 | 32 | MPI_Comm_size(MPI_COMM_WORLD, &world_size); | |
| 310 | 32 | MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); | |
| 311 | |||
| 312 | 32 | int points_count = 0; | |
| 313 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 314 | 16 | points_count = static_cast<int>(GetInput().size()); | |
| 315 | } | ||
| 316 | |||
| 317 | 32 | MPI_Bcast(&points_count, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 318 | |||
| 319 | 32 | const int active_procs = CalculateOptimalActiveProcs(points_count, world_size); | |
| 320 | |||
| 321 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
|
32 | if (active_procs == 1) { |
| 322 | 26 | std::vector<Point> result; | |
| 323 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
|
26 | if (world_rank == 0) { |
| 324 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
26 | result = GrahamScan(GetInput()); |
| 325 | } | ||
| 326 |
3/6✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
52 | GetOutput() = BroadcastFinalResult(world_rank, result); |
| 327 | return true; | ||
| 328 | } | ||
| 329 | |||
| 330 | 6 | int actual_active_procs = 0; | |
| 331 | 6 | const std::vector<Point> local_points = PrepareAndDistributeData(world_rank, world_size, actual_active_procs); | |
| 332 | |||
| 333 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | std::vector<Point> local_hull; |
| 334 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (!local_points.empty()) { |
| 335 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | local_hull = GrahamScan(local_points); |
| 336 | } | ||
| 337 | |||
| 338 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | const std::vector<Point> merged = MergeHullsBinaryTree(world_rank, local_hull, actual_active_procs); |
| 339 | |||
| 340 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
|
6 | const std::vector<Point> root_hull = (world_rank == 0) ? merged : std::vector<Point>{}; |
| 341 | |||
| 342 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
12 | GetOutput() = BroadcastFinalResult(world_rank, root_hull); |
| 343 | return true; | ||
| 344 | } | ||
| 345 | |||
| 346 | 32 | bool LuchnikovEGrahamConvexHullMPI::PostProcessingImpl() { | |
| 347 | 32 | return true; | |
| 348 | } | ||
| 349 | |||
| 350 | } // namespace luchnikov_e_graham_cov_hall_constr | ||
| 351 |