GCC Code Coverage Report


Directory: ./
File: tasks/dolov_v_torus_topology/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 101 110 91.8%
Functions: 9 9 100.0%
Branches: 56 105 53.3%

Line Branch Exec Source
1 #include "dolov_v_torus_topology/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <set>
8 #include <utility>
9 #include <vector>
10
11 #include "dolov_v_torus_topology/common/include/common.hpp"
12
13 namespace dolov_v_torus_topology {
14
15 14 DolovVTorusTopologyMPI::DolovVTorusTopologyMPI(InType in) : input_(std::move(in)) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 14 }
18
19 28 DolovVTorusTopologyMPI::~DolovVTorusTopologyMPI() {
20
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
28 if (torus_comm_ != MPI_COMM_NULL) {
21 28 MPI_Comm_free(&torus_comm_);
22 }
23 56 }
24
25 14 bool DolovVTorusTopologyMPI::ValidationImpl() {
26 14 int proc_count = 0;
27 14 MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
28
3/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 return input_.sender_rank >= 0 && input_.sender_rank < proc_count && input_.receiver_rank >= 0 &&
29
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
28 input_.receiver_rank < proc_count && input_.total_procs == proc_count;
30 }
31
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 bool DolovVTorusTopologyMPI::PreProcessingImpl() {
33 output_.route.clear();
34 output_.received_message.clear();
35
36 14 int rank = 0;
37 14 int proc_count = 0;
38 14 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
39 14 MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
40
41 14 int rows = 0;
42 int cols = 0;
43 14 DefineGridDimensions(proc_count, rows, cols);
44
45 std::set<int> unique_neighbors;
46 28 unique_neighbors.insert(GetTargetNeighbor(rank, MoveSide::kNorth, rows, cols));
47 28 unique_neighbors.insert(GetTargetNeighbor(rank, MoveSide::kSouth, rows, cols));
48 28 unique_neighbors.insert(GetTargetNeighbor(rank, MoveSide::kWest, rows, cols));
49 14 unique_neighbors.insert(GetTargetNeighbor(rank, MoveSide::kEast, rows, cols));
50
51 unique_neighbors.erase(rank);
52
53
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 std::vector<int> neighbors(unique_neighbors.begin(), unique_neighbors.end());
54 14 int degrees = static_cast<int>(neighbors.size());
55
56
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, degrees, neighbors.data(), MPI_UNWEIGHTED, degrees, neighbors.data(),
57 MPI_UNWEIGHTED, MPI_INFO_NULL, 0, &torus_comm_);
58
59
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
28 return torus_comm_ != MPI_COMM_NULL;
60 }
61
62 14 bool DolovVTorusTopologyMPI::RunImpl() {
63 14 int rank = 0;
64 14 int proc_count = 0;
65 14 MPI_Comm_rank(torus_comm_, &rank);
66 14 MPI_Comm_size(torus_comm_, &proc_count);
67
68 14 int rows = 0;
69 int cols = 0;
70 14 DefineGridDimensions(proc_count, rows, cols);
71
72
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 int msg_size = (rank == input_.sender_rank) ? static_cast<int>(input_.message.size()) : 0;
73 14 MPI_Bcast(&msg_size, 1, MPI_INT, input_.sender_rank, torus_comm_);
74
75 14 std::vector<int> current_msg;
76
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (rank == input_.sender_rank) {
77
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 current_msg = input_.message;
78 } else {
79
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 current_msg.resize(static_cast<std::size_t>(msg_size));
80 }
81
82 14 int current_node = input_.sender_rank;
83
1/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
14 std::vector<int> path = {current_node};
84
85
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 14 times.
22 while (current_node != input_.receiver_rank) {
86 8 MoveSide next_step = FindShortestPathStep(current_node, input_.receiver_rank, rows, cols);
87 8 int next_node = GetTargetNeighbor(current_node, next_step, rows, cols);
88
89
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == current_node) {
90
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Send(current_msg.data(), msg_size, MPI_INT, next_node, ProtocolTags::kDataTransfer, torus_comm_);
91 4 int p_size = static_cast<int>(path.size());
92
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Send(&p_size, 1, MPI_INT, next_node, ProtocolTags::kRouteSync, torus_comm_);
93
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Send(path.data(), p_size, MPI_INT, next_node, ProtocolTags::kRouteSync, torus_comm_);
94
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (rank == next_node) {
95
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Recv(current_msg.data(), msg_size, MPI_INT, current_node, ProtocolTags::kDataTransfer, torus_comm_,
96 MPI_STATUS_IGNORE);
97 4 int p_size = 0;
98
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Recv(&p_size, 1, MPI_INT, current_node, ProtocolTags::kRouteSync, torus_comm_, MPI_STATUS_IGNORE);
99
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 path.resize(static_cast<std::size_t>(p_size));
100
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Recv(path.data(), p_size, MPI_INT, current_node, ProtocolTags::kRouteSync, torus_comm_, MPI_STATUS_IGNORE);
101 path.push_back(next_node);
102 }
103
104 8 int prev_owner = current_node;
105 8 current_node = next_node;
106
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(&current_node, 1, MPI_INT, prev_owner, torus_comm_);
107 }
108
109
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (rank == input_.receiver_rank) {
110 7 output_.received_message = std::move(current_msg);
111 7 output_.route = std::move(path);
112 }
113
114
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 int final_path_size = (rank == input_.receiver_rank) ? static_cast<int>(output_.route.size()) : 0;
115
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 MPI_Bcast(&final_path_size, 1, MPI_INT, input_.receiver_rank, torus_comm_);
116
117
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (rank != input_.receiver_rank) {
118
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 output_.route.resize(static_cast<std::size_t>(final_path_size));
119 }
120
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 MPI_Bcast(output_.route.data(), final_path_size, MPI_INT, input_.receiver_rank, torus_comm_);
121
122
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (rank != input_.receiver_rank) {
123
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 output_.received_message.resize(static_cast<std::size_t>(msg_size));
124 }
125
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 MPI_Bcast(output_.received_message.data(), msg_size, MPI_INT, input_.receiver_rank, torus_comm_);
126
127 14 return true;
128 }
129
130 28 void DolovVTorusTopologyMPI::DefineGridDimensions(int total_procs, int &r, int &c) {
131 28 r = static_cast<int>(std::sqrt(total_procs));
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 while (total_procs % r != 0) {
133 r--;
134 }
135 28 c = total_procs / r;
136 28 }
137
138 8 DolovVTorusTopologyMPI::MoveSide DolovVTorusTopologyMPI::FindShortestPathStep(int current, int target, int r, int c) {
139 8 int curr_x = current % c;
140 8 int curr_y = current / c;
141 8 int tar_x = target % c;
142 8 int tar_y = target / c;
143 8 int dx = tar_x - curr_x;
144 8 int dy = tar_y - curr_y;
145
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (std::abs(dx) > c / 2) {
147 dx = (dx > 0) ? dx - c : dx + c;
148 }
149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (std::abs(dy) > r / 2) {
150 dy = (dy > 0) ? dy - r : dy + r;
151 }
152
153
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (dx != 0) {
154
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
10 return (dx > 0) ? MoveSide::kEast : MoveSide::kWest;
155 }
156 if (dy != 0) {
157 return (dy > 0) ? MoveSide::kSouth : MoveSide::kNorth;
158 }
159 return MoveSide::kStay;
160 }
161
162 8 int DolovVTorusTopologyMPI::GetTargetNeighbor(int current, MoveSide side, int r, int c) {
163 64 int x = current % c;
164 64 int y = current / c;
165
2/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
8 switch (side) {
166 case MoveSide::kNorth:
167 14 y = (y - 1 + r) % r;
168 break;
169 case MoveSide::kSouth:
170 14 y = (y + 1) % r;
171 break;
172 2 case MoveSide::kWest:
173 16 x = (x - 1 + c) % c;
174 2 break;
175 6 case MoveSide::kEast:
176 20 x = (x + 1) % c;
177 6 break;
178 case MoveSide::kStay:
179 break;
180 }
181
4/8
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
14 return (y * c) + x;
182 }
183
184 14 bool DolovVTorusTopologyMPI::PostProcessingImpl() {
185 GetOutput() = output_;
186 14 return true;
187 }
188
189 } // namespace dolov_v_torus_topology
190