| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "chernov_t_convex_hull_binary_components/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <array> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <cstdint> | ||
| 9 | #include <queue> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "chernov_t_convex_hull_binary_components/common/include/common.hpp" | ||
| 14 | |||
| 15 | namespace chernov_t_convex_hull_binary_components { | ||
| 16 | |||
| 17 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | ChernovTConvexHullBinaryComponentsMPI::ChernovTConvexHullBinaryComponentsMPI(const InType &in) { |
| 18 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 19 | GetInput() = in; | ||
| 20 | 18 | GetOutput() = OutType{}; | |
| 21 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Comm_rank(MPI_COMM_WORLD, &rank_); |
| 22 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Comm_size(MPI_COMM_WORLD, &size_); |
| 23 | 18 | } | |
| 24 | |||
| 25 | 18 | bool ChernovTConvexHullBinaryComponentsMPI::ValidationImpl() { | |
| 26 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 27 | const auto &[w, h, p] = GetInput(); | ||
| 28 |
3/6✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
|
9 | valid_ = (w > 0) && (h > 0) && (p.size() == static_cast<std::size_t>(w) * static_cast<std::size_t>(h)); |
| 29 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (valid_) { |
| 30 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 9 times.
|
75 | for (int px : p) { |
| 31 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if (px != 0 && px != 1) { |
| 32 | ✗ | valid_ = false; | |
| 33 | ✗ | break; | |
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | 18 | MPI_Bcast(&valid_, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); | |
| 39 | 18 | return valid_; | |
| 40 | } | ||
| 41 | |||
| 42 | 18 | bool ChernovTConvexHullBinaryComponentsMPI::PreProcessingImpl() { | |
| 43 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!valid_) { |
| 44 | return false; | ||
| 45 | } | ||
| 46 | |||
| 47 | 18 | std::array<int, 2> dims{0, 0}; | |
| 48 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 49 | 9 | dims[0] = std::get<0>(GetInput()); | |
| 50 | 9 | dims[1] = std::get<1>(GetInput()); | |
| 51 | } | ||
| 52 | 18 | MPI_Bcast(dims.data(), 2, MPI_INT, 0, MPI_COMM_WORLD); | |
| 53 | 18 | width_ = dims[0]; | |
| 54 | 18 | height_ = dims[1]; | |
| 55 | |||
| 56 | 18 | int base_rows = height_ / size_; | |
| 57 | 18 | int rem = height_ % size_; | |
| 58 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | start_row_ = (rank_ * base_rows) + std::min(rank_, rem); |
| 59 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | end_row_ = start_row_ + base_rows + (rank_ < rem ? 1 : 0); |
| 60 | 18 | int local_rows = end_row_ - start_row_; | |
| 61 | |||
| 62 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 63 | const auto &pixels = std::get<2>(GetInput()); | ||
| 64 | 9 | std::vector<int> sendcounts(size_, 0); | |
| 65 |
1/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
9 | std::vector<int> displs(size_, 0); |
| 66 | int offset = 0; | ||
| 67 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 9 times.
|
27 | for (int i = 0; i < size_; ++i) { |
| 68 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | int rows_i = base_rows + (i < rem ? 1 : 0); |
| 69 | 18 | sendcounts[i] = rows_i * width_; | |
| 70 | 18 | displs[i] = offset; | |
| 71 | 18 | offset += sendcounts[i]; | |
| 72 | } | ||
| 73 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | local_pixels_.resize(static_cast<std::size_t>(local_rows) * static_cast<std::size_t>(width_)); |
| 74 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | MPI_Scatterv(pixels.data(), sendcounts.data(), displs.data(), MPI_INT, local_pixels_.data(), |
| 75 | static_cast<int>(local_pixels_.size()), MPI_INT, 0, MPI_COMM_WORLD); | ||
| 76 | } else { | ||
| 77 | 9 | local_pixels_.resize(static_cast<std::size_t>(local_rows) * static_cast<std::size_t>(width_)); | |
| 78 | 9 | MPI_Scatterv(nullptr, nullptr, nullptr, MPI_INT, local_pixels_.data(), static_cast<int>(local_pixels_.size()), | |
| 79 | MPI_INT, 0, MPI_COMM_WORLD); | ||
| 80 | } | ||
| 81 | return true; | ||
| 82 | } | ||
| 83 | |||
| 84 | 18 | void ChernovTConvexHullBinaryComponentsMPI::FindConnectedComponentsMpi() { | |
| 85 | 18 | int local_rows = end_row_ - start_row_; | |
| 86 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
|
18 | if (local_rows == 0) { |
| 87 | 3 | return; | |
| 88 | } | ||
| 89 | |||
| 90 | 15 | bool has_top = (start_row_ > 0); | |
| 91 | 15 | bool has_bottom = (end_row_ < height_); | |
| 92 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6 times.
|
24 | int extended_rows = local_rows + (has_top ? 1 : 0) + (has_bottom ? 1 : 0); |
| 93 | 15 | std::vector<int> extended_pixels(static_cast<std::size_t>(extended_rows) * static_cast<std::size_t>(width_), 0); | |
| 94 | |||
| 95 | int offset = has_top ? 1 : 0; | ||
| 96 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 15 times.
|
34 | for (int local_row = 0; local_row < local_rows; ++local_row) { |
| 97 | 19 | std::size_t src = static_cast<std::size_t>(local_row) * static_cast<std::size_t>(width_); | |
| 98 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | std::size_t dst = static_cast<std::size_t>(offset + local_row) * static_cast<std::size_t>(width_); |
| 99 | std::ranges::copy(local_pixels_.begin() + static_cast<std::ptrdiff_t>(src), | ||
| 100 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | local_pixels_.begin() + static_cast<std::ptrdiff_t>(src + width_), |
| 101 | extended_pixels.begin() + static_cast<std::ptrdiff_t>(dst)); | ||
| 102 | } | ||
| 103 | |||
| 104 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | ExchangeBoundaryRows(has_top, has_bottom, extended_pixels, width_); |
| 105 | |||
| 106 | 15 | int global_y_offset = start_row_ - (has_top ? 1 : 0); | |
| 107 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | auto all_components = ProcessExtendedRegion(extended_pixels, extended_rows, width_, global_y_offset); |
| 108 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | FilterLocalComponents(all_components); |
| 109 | 15 | } | |
| 110 | |||
| 111 | 15 | void ChernovTConvexHullBinaryComponentsMPI::ExchangeBoundaryRows(bool has_top, bool has_bottom, | |
| 112 | std::vector<int> &extended_pixels, int width) { | ||
| 113 | 15 | std::vector<MPI_Request> reqs(4, MPI_REQUEST_NULL); | |
| 114 |
1/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
15 | std::vector<MPI_Status> statuses(4); |
| 115 | int req_count = 0; | ||
| 116 | |||
| 117 | 15 | std::vector<int> top_recv; | |
| 118 | 15 | std::vector<int> bottom_recv; | |
| 119 | |||
| 120 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
|
15 | if (has_top) { |
| 121 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | top_recv.resize(width); |
| 122 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | std::vector<int> top_send(local_pixels_.begin(), local_pixels_.begin() + width); |
| 123 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Irecv(top_recv.data(), width, MPI_INT, rank_ - 1, 1, MPI_COMM_WORLD, &reqs[req_count]); |
| 124 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Isend(top_send.data(), width, MPI_INT, rank_ - 1, 0, MPI_COMM_WORLD, &reqs[req_count + 1]); |
| 125 | req_count += 2; | ||
| 126 | } | ||
| 127 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
15 | if (has_bottom && rank_ + 1 < size_) { |
| 128 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | bottom_recv.resize(width); |
| 129 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<int> bottom_send(local_pixels_.end() - width, local_pixels_.end()); |
| 130 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Irecv(bottom_recv.data(), width, MPI_INT, rank_ + 1, 0, MPI_COMM_WORLD, &reqs[req_count]); |
| 131 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Isend(bottom_send.data(), width, MPI_INT, rank_ + 1, 1, MPI_COMM_WORLD, &reqs[req_count + 1]); |
| 132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | req_count += 2; |
| 133 | } | ||
| 134 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
|
15 | if (req_count > 0) { |
| 135 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | MPI_Waitall(req_count, reqs.data(), statuses.data()); |
| 136 | } | ||
| 137 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
|
15 | if (has_top) { |
| 138 | std::ranges::copy(top_recv, extended_pixels.begin()); | ||
| 139 | } | ||
| 140 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
15 | if (has_bottom && rank_ + 1 < size_) { |
| 141 | std::ranges::copy(bottom_recv, extended_pixels.end() - width); | ||
| 142 | } | ||
| 143 | 15 | } | |
| 144 | |||
| 145 | 30 | std::vector<std::pair<int, int>> ChernovTConvexHullBinaryComponentsMPI::ExtractComponent( | |
| 146 | int start_col, int start_ey, const std::vector<int> &extended_pixels, std::vector<std::vector<bool>> &visited, | ||
| 147 | int width, int extended_rows, int global_y_offset) { | ||
| 148 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | std::vector<std::pair<int, int>> comp; |
| 149 | std::queue<std::pair<int, int>> q; | ||
| 150 | q.emplace(start_col, start_ey); | ||
| 151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | visited[static_cast<std::size_t>(start_ey)][static_cast<std::size_t>(start_col)] = true; |
| 152 | |||
| 153 | 30 | constexpr std::array<std::pair<int, int>, 4> kDirs = {{{0, -1}, {0, 1}, {-1, 0}, {1, 0}}}; | |
| 154 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 30 times.
|
85 | while (!q.empty()) { |
| 155 | auto [cx, cy] = q.front(); | ||
| 156 | q.pop(); | ||
| 157 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | comp.emplace_back(cx, global_y_offset + cy); |
| 158 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 55 times.
|
275 | for (const auto &[dx, dy] : kDirs) { |
| 159 | 220 | int nx = cx + dx; | |
| 160 | 220 | int ny = cy + dy; | |
| 161 |
8/8✓ Branch 0 taken 204 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 187 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 158 times.
✓ Branch 5 taken 29 times.
✓ Branch 6 taken 129 times.
✓ Branch 7 taken 29 times.
|
220 | if (nx >= 0 && nx < width && ny >= 0 && ny < extended_rows) { |
| 162 | 129 | std::size_t nidx = | |
| 163 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 67 times.
|
129 | (static_cast<std::size_t>(ny) * static_cast<std::size_t>(width)) + static_cast<std::size_t>(nx); |
| 164 |
4/4✓ Branch 0 taken 62 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 37 times.
|
129 | if (extended_pixels[nidx] == 1 && !visited[static_cast<std::size_t>(ny)][static_cast<std::size_t>(nx)]) { |
| 165 | visited[static_cast<std::size_t>(ny)][static_cast<std::size_t>(nx)] = true; | ||
| 166 | q.emplace(nx, ny); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | 30 | return comp; | |
| 172 | } | ||
| 173 | |||
| 174 | 15 | std::vector<std::vector<std::pair<int, int>>> ChernovTConvexHullBinaryComponentsMPI::ProcessExtendedRegion( | |
| 175 | const std::vector<int> &extended_pixels, int extended_rows, int width, int global_y_offset) { | ||
| 176 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | std::vector<std::vector<bool>> visited(extended_rows, std::vector<bool>(width, false)); |
| 177 | 15 | std::vector<std::vector<std::pair<int, int>>> all_components; | |
| 178 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 15 times.
|
46 | for (int ey = 0; ey < extended_rows; ++ey) { |
| 179 |
2/2✓ Branch 0 taken 104 times.
✓ Branch 1 taken 31 times.
|
135 | for (int col = 0; col < width; ++col) { |
| 180 | 104 | std::size_t idx = | |
| 181 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 49 times.
|
104 | (static_cast<std::size_t>(ey) * static_cast<std::size_t>(width)) + static_cast<std::size_t>(col); |
| 182 |
4/4✓ Branch 0 taken 55 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 25 times.
|
104 | if (extended_pixels[idx] == 1 && !visited[static_cast<std::size_t>(ey)][static_cast<std::size_t>(col)]) { |
| 183 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | auto comp = ExtractComponent(col, ey, extended_pixels, visited, width, extended_rows, global_y_offset); |
| 184 | all_components.push_back(std::move(comp)); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | 15 | return all_components; | |
| 189 | 15 | } | |
| 190 | |||
| 191 | 15 | void ChernovTConvexHullBinaryComponentsMPI::FilterLocalComponents( | |
| 192 | const std::vector<std::vector<std::pair<int, int>>> &all_components) { | ||
| 193 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 15 times.
|
45 | for (const auto &comp : all_components) { |
| 194 | 30 | std::vector<std::pair<int, int>> local_comp; | |
| 195 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 30 times.
|
85 | for (auto [px, py] : comp) { |
| 196 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 10 times.
|
55 | if (py >= start_row_ && py < end_row_) { |
| 197 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | local_comp.emplace_back(px, py); |
| 198 | } | ||
| 199 | } | ||
| 200 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 8 times.
|
30 | if (!local_comp.empty()) { |
| 201 | std::ranges::sort(local_comp); | ||
| 202 | auto [first, last] = std::ranges::unique(local_comp); | ||
| 203 | local_comp.erase(first, last); | ||
| 204 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | local_hulls_.push_back(std::move(local_comp)); |
| 205 | } | ||
| 206 | } | ||
| 207 | 15 | } | |
| 208 | |||
| 209 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
|
22 | std::vector<std::pair<int, int>> ChernovTConvexHullBinaryComponentsMPI::ConvexHull( |
| 210 | std::vector<std::pair<int, int>> pts) { | ||
| 211 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
|
22 | if (pts.size() <= 1U) { |
| 212 | return pts; | ||
| 213 | } | ||
| 214 | std::ranges::sort(pts); | ||
| 215 | auto [first, last] = std::ranges::unique(pts); | ||
| 216 | pts.erase(first, last); | ||
| 217 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | if (pts.size() <= 2U) { |
| 218 | return pts; | ||
| 219 | } | ||
| 220 | |||
| 221 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::vector<std::pair<int, int>> hull; |
| 222 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | hull.reserve(pts.size() + 1); |
| 223 | |||
| 224 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
|
11 | for (const auto &p : pts) { |
| 225 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
|
14 | while (hull.size() >= 2) { |
| 226 | const auto &a = hull[hull.size() - 2]; | ||
| 227 | const auto &b = hull[hull.size() - 1]; | ||
| 228 | 5 | std::int64_t cross = | |
| 229 | 5 | (static_cast<std::int64_t>(b.first - a.first) * static_cast<std::int64_t>(p.second - a.second)) - | |
| 230 | 5 | (static_cast<std::int64_t>(b.second - a.second) * static_cast<std::int64_t>(p.first - a.first)); | |
| 231 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (cross > 0) { |
| 232 | break; | ||
| 233 | } | ||
| 234 | hull.pop_back(); | ||
| 235 | } | ||
| 236 | hull.push_back(p); | ||
| 237 | } | ||
| 238 | |||
| 239 | std::size_t lower_len = hull.size(); | ||
| 240 | |||
| 241 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
9 | for (auto it = pts.rbegin() + 1; it != pts.rend(); ++it) { |
| 242 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
12 | while (hull.size() > lower_len) { |
| 243 | const auto &a = hull[hull.size() - 2]; | ||
| 244 | const auto &b = hull[hull.size() - 1]; | ||
| 245 | std::int64_t cross = | ||
| 246 | 5 | (static_cast<std::int64_t>(b.first - a.first) * static_cast<std::int64_t>(it->second - a.second)) - | |
| 247 | 5 | (static_cast<std::int64_t>(b.second - a.second) * static_cast<std::int64_t>(it->first - a.first)); | |
| 248 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (cross > 0) { |
| 249 | break; | ||
| 250 | } | ||
| 251 | hull.pop_back(); | ||
| 252 | } | ||
| 253 | hull.push_back(*it); | ||
| 254 | } | ||
| 255 | |||
| 256 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (hull.size() > 1) { |
| 257 | hull.pop_back(); | ||
| 258 | } | ||
| 259 | return hull; | ||
| 260 | } | ||
| 261 | |||
| 262 | 18 | void ChernovTConvexHullBinaryComponentsMPI::ComputeConvexHulls() { | |
| 263 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
|
40 | for (auto &comp : local_hulls_) { |
| 264 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
44 | comp = ConvexHull(comp); |
| 265 | } | ||
| 266 | 18 | } | |
| 267 | |||
| 268 | 9 | void ChernovTConvexHullBinaryComponentsMPI::GatherHullsOnRank0(std::vector<int> &all_sizes, | |
| 269 | std::vector<int> &global_flat) { | ||
| 270 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
18 | all_sizes = std::vector<int>(local_hulls_.size()); |
| 271 | global_flat.clear(); | ||
| 272 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 9 times.
|
23 | for (size_t i = 0; i < local_hulls_.size(); ++i) { |
| 273 | 14 | all_sizes[i] = static_cast<int>(local_hulls_[i].size()); | |
| 274 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 14 times.
|
33 | for (const auto &p : local_hulls_[i]) { |
| 275 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
|
19 | global_flat.push_back(p.first); |
| 276 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8 times.
|
19 | global_flat.push_back(p.second); |
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | for (int src = 1; src < size_; ++src) { |
| 281 | 9 | ReceiveHullsFromRank(src, all_sizes, global_flat); | |
| 282 | } | ||
| 283 | 9 | } | |
| 284 | |||
| 285 | 18 | void ChernovTConvexHullBinaryComponentsMPI::BroadcastResultToAllRanks( | |
| 286 | const std::vector<std::vector<std::pair<int, int>>> &global_hulls) { | ||
| 287 | 18 | int total_hulls = static_cast<int>(global_hulls.size()); | |
| 288 | 18 | MPI_Bcast(&total_hulls, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 289 | |||
| 290 | 18 | std::vector<int> all_sizes(total_hulls); | |
| 291 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 292 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 9 times.
|
31 | for (int i = 0; i < total_hulls; ++i) { |
| 293 | 22 | all_sizes[i] = static_cast<int>(global_hulls[static_cast<std::size_t>(i)].size()); | |
| 294 | } | ||
| 295 | } | ||
| 296 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Bcast(all_sizes.data(), total_hulls, MPI_INT, 0, MPI_COMM_WORLD); |
| 297 | |||
| 298 | 18 | int total_pts = 0; | |
| 299 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 18 times.
|
62 | for (int s : all_sizes) { |
| 300 | 44 | total_pts += s; | |
| 301 | } | ||
| 302 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Bcast(&total_pts, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 303 | |||
| 304 |
1/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18 | std::vector<int> flat(static_cast<std::size_t>(total_pts) * 2); |
| 305 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 306 | flat.clear(); | ||
| 307 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 9 times.
|
31 | for (const auto &h : global_hulls) { |
| 308 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 22 times.
|
52 | for (const auto &p : h) { |
| 309 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | flat.push_back(p.first); |
| 310 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | flat.push_back(p.second); |
| 311 | } | ||
| 312 | } | ||
| 313 | } | ||
| 314 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Bcast(flat.data(), total_pts * 2, MPI_INT, 0, MPI_COMM_WORLD); |
| 315 | |||
| 316 | 18 | OutType result; | |
| 317 | std::size_t idx = 0; | ||
| 318 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 18 times.
|
62 | for (int i = 0; i < total_hulls; ++i) { |
| 319 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | int sz = all_sizes[i]; |
| 320 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | std::vector<std::pair<int, int>> hull(static_cast<std::size_t>(sz)); |
| 321 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 44 times.
|
104 | for (int j = 0; j < sz; ++j, idx += 2) { |
| 322 | 60 | hull[static_cast<std::size_t>(j)] = {flat[idx], flat[idx + 1]}; | |
| 323 | } | ||
| 324 | result.push_back(std::move(hull)); | ||
| 325 | } | ||
| 326 | 18 | GetOutput() = std::move(result); | |
| 327 | 36 | } | |
| 328 | |||
| 329 | 18 | void ChernovTConvexHullBinaryComponentsMPI::GatherAndBroadcastResult() { | |
| 330 | 18 | std::vector<int> local_flat; | |
| 331 | 18 | std::vector<int> local_sizes; | |
| 332 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
|
40 | for (const auto &hull : local_hulls_) { |
| 333 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | local_sizes.push_back(static_cast<int>(hull.size())); |
| 334 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 22 times.
|
52 | for (const auto &p : hull) { |
| 335 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
|
30 | local_flat.push_back(p.first); |
| 336 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 13 times.
|
30 | local_flat.push_back(p.second); |
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank_ == 0) { |
| 341 | 9 | std::vector<int> all_sizes; | |
| 342 | 9 | std::vector<int> global_flat; | |
| 343 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | GatherHullsOnRank0(all_sizes, global_flat); |
| 344 | |||
| 345 | 9 | OutType global_hulls; | |
| 346 | std::size_t idx = 0; | ||
| 347 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 9 times.
|
31 | for (int sz : all_sizes) { |
| 348 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | std::vector<std::pair<int, int>> hull(static_cast<std::size_t>(sz)); |
| 349 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 22 times.
|
52 | for (int j = 0; j < sz; ++j, idx += 2) { |
| 350 | 30 | hull[static_cast<std::size_t>(j)] = {global_flat[idx], global_flat[idx + 1]}; | |
| 351 | } | ||
| 352 | global_hulls.push_back(std::move(hull)); | ||
| 353 | } | ||
| 354 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | BroadcastResultToAllRanks(global_hulls); |
| 355 | 9 | } else { | |
| 356 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | SendHullsToRank0(local_flat, local_sizes); |
| 357 |
1/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
9 | BroadcastResultToAllRanks({}); |
| 358 | } | ||
| 359 | 18 | } | |
| 360 | |||
| 361 | 9 | void ChernovTConvexHullBinaryComponentsMPI::SendHullsToRank0(const std::vector<int> &local_flat, | |
| 362 | const std::vector<int> &local_sizes) { | ||
| 363 | 9 | int count = static_cast<int>(local_sizes.size()); | |
| 364 | 9 | MPI_Send(&count, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); | |
| 365 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (count > 0) { |
| 366 | 5 | MPI_Send(local_sizes.data(), count, MPI_INT, 0, 1, MPI_COMM_WORLD); | |
| 367 | 5 | int pts = static_cast<int>(local_flat.size() / 2); | |
| 368 | 5 | MPI_Send(&pts, 1, MPI_INT, 0, 2, MPI_COMM_WORLD); | |
| 369 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (pts > 0) { |
| 370 | 5 | MPI_Send(local_flat.data(), static_cast<int>(local_flat.size()), MPI_INT, 0, 3, MPI_COMM_WORLD); | |
| 371 | } | ||
| 372 | } | ||
| 373 | 9 | } | |
| 374 | |||
| 375 | 9 | void ChernovTConvexHullBinaryComponentsMPI::ReceiveHullsFromRank(int src, std::vector<int> &all_sizes, | |
| 376 | std::vector<int> &global_flat) { | ||
| 377 | 9 | int count = 0; | |
| 378 | 9 | MPI_Recv(&count, 1, MPI_INT, src, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | |
| 379 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (count > 0) { |
| 380 | 5 | std::vector<int> sizes(static_cast<std::size_t>(count)); | |
| 381 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | MPI_Recv(sizes.data(), count, MPI_INT, src, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); |
| 382 | 5 | all_sizes.insert(all_sizes.end(), sizes.begin(), sizes.end()); | |
| 383 | 5 | int pts = 0; | |
| 384 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | MPI_Recv(&pts, 1, MPI_INT, src, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE); |
| 385 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (pts > 0) { |
| 386 |
1/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
5 | std::vector<int> pts_data(static_cast<std::size_t>(pts) * 2); |
| 387 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | MPI_Recv(pts_data.data(), pts * 2, MPI_INT, src, 3, MPI_COMM_WORLD, MPI_STATUS_IGNORE); |
| 388 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | global_flat.insert(global_flat.end(), pts_data.begin(), pts_data.end()); |
| 389 | } | ||
| 390 | } | ||
| 391 | 9 | } | |
| 392 | |||
| 393 | 18 | bool ChernovTConvexHullBinaryComponentsMPI::RunImpl() { | |
| 394 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (!valid_) { |
| 395 | ✗ | GetOutput() = OutType{}; | |
| 396 | ✗ | return true; | |
| 397 | } | ||
| 398 | 18 | FindConnectedComponentsMpi(); | |
| 399 | 18 | ComputeConvexHulls(); | |
| 400 | 18 | GatherAndBroadcastResult(); | |
| 401 | 18 | return true; | |
| 402 | } | ||
| 403 | |||
| 404 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | bool ChernovTConvexHullBinaryComponentsMPI::PostProcessingImpl() { |
| 405 | local_pixels_.clear(); | ||
| 406 | local_hulls_.clear(); | ||
| 407 | 18 | return true; | |
| 408 | } | ||
| 409 | |||
| 410 | } // namespace chernov_t_convex_hull_binary_components | ||
| 411 |