| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "olesnitskiy_v_dijkstra_crs/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstddef> | ||
| 7 | #include <limits> | ||
| 8 | #include <queue> | ||
| 9 | #include <tuple> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "olesnitskiy_v_dijkstra_crs/common/include/common.hpp" | ||
| 13 | |||
| 14 | namespace olesnitskiy_v_dijkstra_crs { | ||
| 15 | |||
| 16 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | OlesnitskiyVDijkstraCrsMPI::OlesnitskiyVDijkstraCrsMPI(const InType &in) { |
| 17 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 18 | GetInput() = in; | ||
| 19 | 28 | GetOutput() = std::vector<int>(); | |
| 20 | 28 | } | |
| 21 | |||
| 22 | 28 | bool OlesnitskiyVDijkstraCrsMPI::ValidationImpl() { | |
| 23 | const auto &input = GetInput(); | ||
| 24 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | int source = std::get<0>(input); |
| 25 | const auto &offsets = std::get<1>(input); | ||
| 26 | const auto &edges = std::get<2>(input); | ||
| 27 | const auto &weights = std::get<3>(input); | ||
| 28 | |||
| 29 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (offsets.empty()) { |
| 30 | return false; | ||
| 31 | } | ||
| 32 | 28 | int vertices = static_cast<int>(offsets.size()) - 1; | |
| 33 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (vertices <= 0) { |
| 34 | return false; | ||
| 35 | } | ||
| 36 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (source < 0 || source >= vertices) { |
| 37 | return false; | ||
| 38 | } | ||
| 39 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (edges.size() != weights.size()) { |
| 40 | ✗ | return false; | |
| 41 | } | ||
| 42 | |||
| 43 | return true; | ||
| 44 | } | ||
| 45 | |||
| 46 | 28 | bool OlesnitskiyVDijkstraCrsMPI::PreProcessingImpl() { | |
| 47 | 28 | return true; | |
| 48 | } | ||
| 49 | |||
| 50 | ✗ | bool OlesnitskiyVDijkstraCrsMPI::IsVertexLocal(int vertex, int start_idx, int end_idx) { | |
| 51 | 267 | return vertex >= start_idx && vertex < end_idx; | |
| 52 | } | ||
| 53 | |||
| 54 | ✗ | int OlesnitskiyVDijkstraCrsMPI::FindOwner(int vertex, const std::vector<int> &displs, const std::vector<int> &counts, | |
| 55 | int size) { | ||
| 56 |
1/4✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
273 | for (int j = 0; j < size; ++j) { |
| 57 |
3/8✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 186 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
273 | if (vertex >= displs[j] && vertex < (displs[j] + counts[j])) { |
| 58 | return j; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | 81 | void OlesnitskiyVDijkstraCrsMPI::ProcessLocalVertex(int vertex, int distance, const std::vector<int> &offsets, | |
| 65 | const std::vector<int> &edges, const std::vector<int> &weights, | ||
| 66 | DijkstraContext &ctx, int rank, int size) { | ||
| 67 | 81 | int start = offsets[vertex]; | |
| 68 | 81 | int end = offsets[vertex + 1]; | |
| 69 | |||
| 70 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 81 times.
|
267 | for (int i = start; i < end; ++i) { |
| 71 | 186 | int neighbor = edges[i]; | |
| 72 | 186 | int weight = weights[i]; | |
| 73 | 186 | int new_dist = distance + weight; | |
| 74 | |||
| 75 | int owner = FindOwner(neighbor, ctx.displs, ctx.counts, size); | ||
| 76 | |||
| 77 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 77 times.
|
186 | if (owner == rank) { |
| 78 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
|
109 | int neighbor_local_idx = neighbor - ctx.start_idx; |
| 79 |
4/4✓ Branch 0 taken 58 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 15 times.
|
109 | if (!ctx.local_visited[neighbor_local_idx] && new_dist < ctx.local_distances[neighbor_local_idx]) { |
| 80 | 43 | ctx.local_distances[neighbor_local_idx] = new_dist; | |
| 81 | 43 | ctx.pq.emplace(new_dist, neighbor); | |
| 82 | } | ||
| 83 | } else { | ||
| 84 | 77 | ctx.send_bufs[owner].push_back(Update{.vertex = neighbor, .distance = new_dist}); | |
| 85 | } | ||
| 86 | } | ||
| 87 | 81 | } | |
| 88 | |||
| 89 | 162 | void OlesnitskiyVDijkstraCrsMPI::PrepareSendData(const std::vector<std::vector<Update>> &send_bufs, | |
| 90 | std::vector<int> &send_data) { | ||
| 91 | int idx = 0; | ||
| 92 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 162 times.
|
486 | for (const auto &send_buf : send_bufs) { |
| 93 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 324 times.
|
401 | for (const auto &update : send_buf) { |
| 94 | 77 | send_data[idx++] = update.vertex; | |
| 95 | 77 | send_data[idx++] = update.distance; | |
| 96 | } | ||
| 97 | } | ||
| 98 | 162 | } | |
| 99 | |||
| 100 | 162 | void OlesnitskiyVDijkstraCrsMPI::ProcessReceivedData(const std::vector<int> &recv_data, int total_recv, | |
| 101 | DijkstraContext &ctx) { | ||
| 102 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 162 times.
|
239 | for (int i = 0; i < total_recv * 2; i += 2) { |
| 103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | int neighbor = recv_data[i]; |
| 104 | 77 | int new_dist = recv_data[i + 1]; | |
| 105 | |||
| 106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | if (!IsVertexLocal(neighbor, ctx.start_idx, ctx.end_idx)) { |
| 107 | 50 | continue; | |
| 108 | } | ||
| 109 | |||
| 110 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 35 times.
|
77 | int local_idx = neighbor - ctx.start_idx; |
| 111 |
4/4✓ Branch 0 taken 42 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 15 times.
|
77 | bool should_update = !ctx.local_visited[local_idx] && new_dist < ctx.local_distances[local_idx]; |
| 112 | 50 | if (!should_update) { | |
| 113 | 50 | continue; | |
| 114 | } | ||
| 115 | |||
| 116 | 27 | ctx.local_distances[local_idx] = new_dist; | |
| 117 | 27 | ctx.pq.emplace(new_dist, neighbor); | |
| 118 | } | ||
| 119 | 162 | } | |
| 120 | |||
| 121 | ✗ | void OlesnitskiyVDijkstraCrsMPI::CalculateDisplacements(const std::vector<int> &sizes, std::vector<int> &displs, | |
| 122 | int &total) { | ||
| 123 | ✗ | total = 0; | |
| 124 |
4/6✓ Branch 0 taken 324 times.
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 162 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
972 | for (size_t i = 0; i < sizes.size(); ++i) { |
| 125 | 648 | displs[i] = total; | |
| 126 | 648 | total += sizes[i]; | |
| 127 | } | ||
| 128 | ✗ | } | |
| 129 | |||
| 130 | ✗ | void OlesnitskiyVDijkstraCrsMPI::PrepareByteArrays(const std::vector<int> &sizes, const std::vector<int> &displs, | |
| 131 | std::vector<int> &counts_bytes, std::vector<int> &displs_bytes) { | ||
| 132 |
4/6✓ Branch 0 taken 324 times.
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 162 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
972 | for (size_t i = 0; i < sizes.size(); ++i) { |
| 133 | 648 | counts_bytes[i] = sizes[i] * 2; | |
| 134 | 648 | displs_bytes[i] = displs[i] * 2; | |
| 135 | } | ||
| 136 | ✗ | } | |
| 137 | |||
| 138 | 162 | void OlesnitskiyVDijkstraCrsMPI::ExchangeUpdates(DijkstraContext &ctx) { | |
| 139 | 162 | int size = static_cast<int>(ctx.send_bufs.size()); | |
| 140 | 162 | std::vector<int> send_sizes(size); | |
| 141 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> recv_sizes(size); |
| 142 | |||
| 143 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 162 times.
|
486 | for (int i = 0; i < size; ++i) { |
| 144 | 324 | send_sizes[i] = static_cast<int>(ctx.send_bufs[i].size()); | |
| 145 | } | ||
| 146 | |||
| 147 |
1/2✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
|
162 | MPI_Alltoall(send_sizes.data(), 1, MPI_INT, recv_sizes.data(), 1, MPI_INT, MPI_COMM_WORLD); |
| 148 | |||
| 149 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> send_displs(size); |
| 150 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> recv_displs(size); |
| 151 | int total_send = 0; | ||
| 152 | int total_recv = 0; | ||
| 153 | |||
| 154 | CalculateDisplacements(send_sizes, send_displs, total_send); | ||
| 155 | CalculateDisplacements(recv_sizes, recv_displs, total_recv); | ||
| 156 | |||
| 157 | 162 | const auto send_data_size = static_cast<std::size_t>(total_send) * 2U; | |
| 158 | 162 | const auto recv_data_size = static_cast<std::size_t>(total_recv) * 2U; | |
| 159 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> send_data(send_data_size); |
| 160 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> recv_data(recv_data_size); |
| 161 | |||
| 162 | 162 | PrepareSendData(ctx.send_bufs, send_data); | |
| 163 | |||
| 164 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 162 times.
|
486 | for (int i = 0; i < size; ++i) { |
| 165 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 283 times.
|
324 | ctx.send_bufs[i].clear(); |
| 166 | } | ||
| 167 | |||
| 168 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> send_counts_bytes(size); |
| 169 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> recv_counts_bytes(size); |
| 170 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> send_displs_bytes(size); |
| 171 |
1/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
162 | std::vector<int> recv_displs_bytes(size); |
| 172 | |||
| 173 | PrepareByteArrays(send_sizes, send_displs, send_counts_bytes, send_displs_bytes); | ||
| 174 | PrepareByteArrays(recv_sizes, recv_displs, recv_counts_bytes, recv_displs_bytes); | ||
| 175 | |||
| 176 |
1/2✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
|
162 | MPI_Alltoallv(send_data.data(), send_counts_bytes.data(), send_displs_bytes.data(), MPI_INT, recv_data.data(), |
| 177 | recv_counts_bytes.data(), recv_displs_bytes.data(), MPI_INT, MPI_COMM_WORLD); | ||
| 178 | |||
| 179 |
1/2✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
|
162 | ProcessReceivedData(recv_data, total_recv, ctx); |
| 180 | 162 | } | |
| 181 | |||
| 182 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | OlesnitskiyVDijkstraCrsMPI::DijkstraContext OlesnitskiyVDijkstraCrsMPI::InitializeLocalData(int vertices, int size, |
| 183 | int rank, int source) { | ||
| 184 | DijkstraContext ctx; | ||
| 185 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.counts.resize(size); |
| 186 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.displs.resize(size); |
| 187 | |||
| 188 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 28 times.
|
84 | for (int idx = 0; idx < size; ++idx) { |
| 189 |
4/4✓ Branch 0 taken 46 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 28 times.
|
102 | ctx.counts[idx] = (vertices / size) + (idx < (vertices % size) ? 1 : 0); |
| 190 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
|
56 | ctx.displs[idx] = (idx == 0) ? 0 : ctx.displs[idx - 1] + ctx.counts[idx - 1]; |
| 191 | } | ||
| 192 | |||
| 193 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.start_idx = ctx.displs[rank]; |
| 194 | 28 | ctx.end_idx = ctx.start_idx + ctx.counts[rank]; | |
| 195 | 28 | ctx.local_vertices = ctx.counts[rank]; | |
| 196 | |||
| 197 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.local_distances.resize(ctx.local_vertices, std::numeric_limits<int>::max()); |
| 198 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.local_visited.resize(ctx.local_vertices, false); |
| 199 | |||
| 200 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (IsVertexLocal(source, ctx.start_idx, ctx.end_idx)) { |
| 201 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | ctx.local_distances[source - ctx.start_idx] = 0; |
| 202 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | ctx.pq.emplace(0, source); |
| 203 | } | ||
| 204 | |||
| 205 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | ctx.send_bufs.resize(size); |
| 206 | 28 | return ctx; | |
| 207 | ✗ | } | |
| 208 | |||
| 209 | 28 | OlesnitskiyVDijkstraCrsMPI::GraphData OlesnitskiyVDijkstraCrsMPI::BroadcastGraphData(int rank, int /*size*/, | |
| 210 | const InType &input) { | ||
| 211 | 28 | GraphData graph; | |
| 212 | |||
| 213 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (rank == 0) { |
| 214 | const auto &inp = input; | ||
| 215 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.source = std::get<0>(inp); |
| 216 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.offsets = std::get<1>(inp); |
| 217 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.edges = std::get<2>(inp); |
| 218 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.weights = std::get<3>(inp); |
| 219 | 14 | graph.vertices = static_cast<int>(graph.offsets.size()) - 1; | |
| 220 | } | ||
| 221 | |||
| 222 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(&graph.vertices, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 223 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(&graph.source, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 224 | |||
| 225 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (rank != 0) { |
| 226 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.offsets.resize(graph.vertices + 1); |
| 227 | } | ||
| 228 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(graph.offsets.data(), graph.vertices + 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 229 | |||
| 230 | 28 | int total_edges = 0; | |
| 231 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (rank == 0) { |
| 232 | 14 | total_edges = static_cast<int>(graph.edges.size()); | |
| 233 | } | ||
| 234 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(&total_edges, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 235 | |||
| 236 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (rank != 0) { |
| 237 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.edges.resize(total_edges); |
| 238 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | graph.weights.resize(total_edges); |
| 239 | } | ||
| 240 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(graph.edges.data(), total_edges, MPI_INT, 0, MPI_COMM_WORLD); |
| 241 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(graph.weights.data(), total_edges, MPI_INT, 0, MPI_COMM_WORLD); |
| 242 | |||
| 243 | 28 | return graph; | |
| 244 | ✗ | } | |
| 245 | |||
| 246 | 167 | bool OlesnitskiyVDijkstraCrsMPI::FindLocalBestVertex(DijkstraContext &ctx, DistVertexPair &local_best) { | |
| 247 | 167 | local_best.dist = std::numeric_limits<int>::max(); | |
| 248 |
2/2✓ Branch 0 taken 103 times.
✓ Branch 1 taken 64 times.
|
167 | local_best.vertex = -1; |
| 249 | |||
| 250 |
2/2✓ Branch 0 taken 103 times.
✓ Branch 1 taken 64 times.
|
167 | if (!ctx.pq.empty()) { |
| 251 | 103 | local_best.dist = ctx.pq.top().first; | |
| 252 | 103 | local_best.vertex = ctx.pq.top().second; | |
| 253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
|
103 | int local_idx = local_best.vertex - ctx.start_idx; |
| 254 | |||
| 255 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 3 times.
|
103 | if (ctx.local_visited[local_idx]) { |
| 256 | 3 | ctx.pq.pop(); | |
| 257 | 3 | return false; | |
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | return true; | ||
| 262 | } | ||
| 263 | |||
| 264 | 164 | OlesnitskiyVDijkstraCrsMPI::DistVertexPair OlesnitskiyVDijkstraCrsMPI::FindGlobalBestVertex( | |
| 265 | const DistVertexPair &local_best) { | ||
| 266 | 164 | DistVertexPair global_best{}; | |
| 267 | 164 | MPI_Allreduce(&local_best, &global_best, 1, MPI_2INT, MPI_MINLOC, MPI_COMM_WORLD); | |
| 268 | 164 | return global_best; | |
| 269 | } | ||
| 270 | |||
| 271 | ✗ | bool OlesnitskiyVDijkstraCrsMPI::ShouldStopAlgorithm(const DistVertexPair &global_best) { | |
| 272 |
3/8✓ Branch 0 taken 162 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
164 | return global_best.vertex == -1 || global_best.dist == std::numeric_limits<int>::max(); |
| 273 | } | ||
| 274 | |||
| 275 | 162 | void OlesnitskiyVDijkstraCrsMPI::ProcessGlobalVertex(const DistVertexPair &global_best, const GraphData &graph, | |
| 276 | DijkstraContext &ctx, int rank, int size) { | ||
| 277 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 81 times.
|
162 | if (!IsVertexLocal(global_best.vertex, ctx.start_idx, ctx.end_idx)) { |
| 278 | return; | ||
| 279 | } | ||
| 280 | |||
| 281 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | int local_idx = global_best.vertex - ctx.start_idx; |
| 282 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | if (ctx.local_visited[local_idx]) { |
| 283 | return; | ||
| 284 | } | ||
| 285 | |||
| 286 | ctx.local_visited[local_idx] = true; | ||
| 287 |
2/4✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
|
81 | if (!ctx.pq.empty() && ctx.pq.top().second == global_best.vertex) { |
| 288 | 81 | ctx.pq.pop(); | |
| 289 | } | ||
| 290 | |||
| 291 | 81 | ProcessLocalVertex(global_best.vertex, global_best.dist, graph.offsets, graph.edges, graph.weights, ctx, rank, size); | |
| 292 | } | ||
| 293 | |||
| 294 | 167 | bool OlesnitskiyVDijkstraCrsMPI::PerformDijkstraIteration(const GraphData &graph, DijkstraContext &ctx, int rank, | |
| 295 | int size) { | ||
| 296 | 167 | DistVertexPair local_best; | |
| 297 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 164 times.
|
167 | if (!FindLocalBestVertex(ctx, local_best)) { |
| 298 | return true; | ||
| 299 | } | ||
| 300 | |||
| 301 | 164 | DistVertexPair global_best = FindGlobalBestVertex(local_best); | |
| 302 | |||
| 303 | if (ShouldStopAlgorithm(global_best)) { | ||
| 304 | return false; | ||
| 305 | } | ||
| 306 | |||
| 307 | 162 | ProcessGlobalVertex(global_best, graph, ctx, rank, size); | |
| 308 | 162 | ExchangeUpdates(ctx); | |
| 309 | |||
| 310 |
2/2✓ Branch 0 taken 74 times.
✓ Branch 1 taken 88 times.
|
162 | int local_active = !ctx.pq.empty() ? 1 : 0; |
| 311 | 162 | MPI_Allreduce(&local_active, &ctx.active, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); | |
| 312 | |||
| 313 | return true; | ||
| 314 | } | ||
| 315 | |||
| 316 | ✗ | void OlesnitskiyVDijkstraCrsMPI::RunDijkstraAlgorithm(const GraphData &graph, DijkstraContext &ctx, int rank, | |
| 317 | int size) { | ||
| 318 | 28 | ctx.active = 1; | |
| 319 |
2/4✓ Branch 0 taken 167 times.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
193 | while (ctx.active > 0) { |
| 320 |
3/6✓ Branch 1 taken 167 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
167 | if (!PerformDijkstraIteration(graph, ctx, rank, size)) { |
| 321 | break; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | ✗ | } | |
| 325 | |||
| 326 | 28 | void OlesnitskiyVDijkstraCrsMPI::CollectResults(const GraphData &graph, const DijkstraContext &ctx, int rank, | |
| 327 | int size) { | ||
| 328 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | if (rank == 0) { |
| 329 | 14 | std::vector<int> global_distances(graph.vertices, std::numeric_limits<int>::max()); | |
| 330 | 14 | std::ranges::copy(ctx.local_distances, global_distances.begin() + ctx.start_idx); | |
| 331 | |||
| 332 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | for (int src = 1; src < size; ++src) { |
| 333 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | MPI_Recv(global_distances.data() + ctx.displs[src], ctx.counts[src], MPI_INT, src, 0, MPI_COMM_WORLD, |
| 334 | MPI_STATUS_IGNORE); | ||
| 335 | } | ||
| 336 | |||
| 337 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | GetOutput() = global_distances; |
| 338 | } else { | ||
| 339 | 14 | MPI_Send(ctx.local_distances.data(), ctx.local_vertices, MPI_INT, 0, 0, MPI_COMM_WORLD); | |
| 340 | 14 | GetOutput() = std::vector<int>(); | |
| 341 | } | ||
| 342 | 28 | } | |
| 343 | |||
| 344 | 28 | bool OlesnitskiyVDijkstraCrsMPI::RunImpl() { | |
| 345 | 28 | int rank = 0; | |
| 346 | 28 | int size = 0; | |
| 347 | 28 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 348 | 28 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 349 | |||
| 350 | 28 | GraphData graph = BroadcastGraphData(rank, size, GetInput()); | |
| 351 | |||
| 352 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | DijkstraContext ctx = InitializeLocalData(graph.vertices, size, rank, graph.source); |
| 353 | |||
| 354 | 28 | RunDijkstraAlgorithm(graph, ctx, rank, size); | |
| 355 | |||
| 356 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | CollectResults(graph, ctx, rank, size); |
| 357 | |||
| 358 | 28 | return true; | |
| 359 | 28 | } | |
| 360 | |||
| 361 | 28 | bool OlesnitskiyVDijkstraCrsMPI::PostProcessingImpl() { | |
| 362 | 28 | return true; | |
| 363 | } | ||
| 364 | } // namespace olesnitskiy_v_dijkstra_crs | ||
| 365 |