GCC Code Coverage Report


Directory: ./
File: tasks/lukin_i_torus_topology/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 96 102 94.1%
Functions: 10 10 100.0%
Branches: 41 74 55.4%

Line Branch Exec Source
1 #include "lukin_i_torus_topology/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <tuple>
7 #include <unordered_map>
8 #include <vector>
9
10 #include "lukin_i_torus_topology/common/include/common.hpp"
11
12 namespace lukin_i_torus_topology {
13
14
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 LukinIThorTopologyMPI::LukinIThorTopologyMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16 GetInput() = in;
17 OutType out = std::make_tuple(std::vector<int>{}, std::vector<int>{});
18 GetOutput() = out;
19 18 }
20
21 18 bool LukinIThorTopologyMPI::ValidationImpl() {
22 18 int start_v = std::get<0>(GetInput());
23 18 int end_v = std::get<1>(GetInput());
24
25
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (start_v < 0 || end_v < 0) {
26 return false;
27 }
28
29 18 int proc_count = -1;
30 18 MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
31
32
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 return start_v <= proc_count - 1 && end_v <= proc_count - 1;
33 }
34
35 18 bool LukinIThorTopologyMPI::PreProcessingImpl() {
36 18 start_ = std::get<0>(GetInput());
37 18 end_ = std::get<1>(GetInput());
38 18 return true;
39 }
40
41 18 bool LukinIThorTopologyMPI::RunImpl() {
42 18 int rank = -1;
43 18 int proc_count = -1;
44 18 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
45 18 MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
46
47 18 std::vector<int> message;
48 18 int message_len = -1;
49
50
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == start_) {
51
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 message = std::get<2>(GetInput());
52 9 message_len = static_cast<int>(message.size());
53 }
54
55
3/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 10 times.
18 if (HandleTrivial(message_len, message, proc_count)) {
56 return true;
57 }
58
59 8 int cols = -1;
60 8 int rows = -1;
61 8 InitTopology(cols, rows, proc_count);
62
63 8 int x = rank % cols;
64 8 int y = rank / cols;
65
66 8 int up = (((y - 1 + rows) % rows) * cols) + x;
67 8 int down = (((y + 1) % rows) * cols) + x;
68 8 int left = (y * cols) + ((x - 1 + cols) % cols);
69
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 int right = (y * cols) + ((x + 1) % cols);
70 std::unordered_map<Direction, int> dir_mapping = {
71 {Direction::kUp, up}, {Direction::kDown, down}, {Direction::kLeft, left}, {Direction::kRight, right}};
72
73 8 int source = start_;
74 8 int dest = -1;
75 8 std::vector<int> full_route;
76 8 int route_size = -1;
77
78 8 int end_x = end_ % cols;
79 8 int end_y = end_ / cols;
80
81
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 while (source != end_) {
82
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == source) {
83
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Direction direction = GetDir(x, y, end_x, end_y, cols, rows);
84 4 dest = dir_mapping[direction];
85 }
86
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(&dest, 1, MPI_INT, source, MPI_COMM_WORLD);
87
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == source) {
88
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Send(message_len, message, full_route, route_size, dest, rank);
89
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (rank == dest) {
90
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Recieve(message_len, message, full_route, route_size, source);
91 }
92 8 source = dest;
93 }
94
95
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == end_) {
96 full_route.push_back(rank);
97 4 route_size = static_cast<int>(full_route.size());
98 }
99
100
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(&route_size, 1, MPI_INT, end_, MPI_COMM_WORLD);
101
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 full_route.resize(route_size);
102
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(full_route.data(), route_size, MPI_INT, end_, MPI_COMM_WORLD);
103
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(&message_len, 1, MPI_INT, end_, MPI_COMM_WORLD);
104
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 message.resize(message_len);
105
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Bcast(message.data(), message_len, MPI_INT, end_, MPI_COMM_WORLD);
106
107
1/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 GetOutput() = std::make_tuple(full_route, message);
108 return true;
109 }
110
111 4 LukinIThorTopologyMPI::Direction LukinIThorTopologyMPI::GetDir(int sx, int sy, int dx, int dy, int cols, int rows) {
112 4 int mx = dx - sx;
113 4 int my = dy - sy;
114
115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (abs(mx) > cols / 2) {
116 mx = mx > 0 ? mx - cols : mx + cols;
117 }
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (abs(my) > rows / 2) {
119 my = my > 0 ? my - rows : my + rows;
120 }
121
122
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (abs(mx) > abs(my)) {
123
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
6 return mx < 0 ? Direction::kLeft : Direction::kRight;
124 }
125
126 return my < 0 ? Direction::kUp : Direction::kDown;
127 }
128
129 18 bool LukinIThorTopologyMPI::PostProcessingImpl() {
130 18 return true;
131 }
132
133 4 void LukinIThorTopologyMPI::Send(int &message_len, std::vector<int> &message, std::vector<int> &full_route,
134 int &route_size, int dest, int rank) {
135 4 MPI_Send(&message_len, 1, MPI_INT, dest, static_cast<int>(Tags::kMlen), MPI_COMM_WORLD);
136 4 MPI_Send(message.data(), message_len, MPI_INT, dest, static_cast<int>(Tags::kMessage), MPI_COMM_WORLD);
137 full_route.push_back(rank);
138 4 route_size = static_cast<int>(full_route.size());
139 4 MPI_Send(&route_size, 1, MPI_INT, dest, static_cast<int>(Tags::kRoutesize), MPI_COMM_WORLD);
140 4 MPI_Send(full_route.data(), route_size, MPI_INT, dest, static_cast<int>(Tags::kRoute), MPI_COMM_WORLD);
141 4 }
142
143 4 void LukinIThorTopologyMPI::Recieve(int &message_len, std::vector<int> &message, std::vector<int> &full_route,
144 int &route_size, int source) {
145 4 MPI_Recv(&message_len, 1, MPI_INT, source, static_cast<int>(Tags::kMlen), MPI_COMM_WORLD, MPI_STATUS_IGNORE);
146 4 message.resize(message_len);
147 4 MPI_Recv(message.data(), message_len, MPI_INT, source, static_cast<int>(Tags::kMessage), MPI_COMM_WORLD,
148 MPI_STATUS_IGNORE);
149 4 MPI_Recv(&route_size, 1, MPI_INT, source, static_cast<int>(Tags::kRoutesize), MPI_COMM_WORLD, MPI_STATUS_IGNORE);
150 4 full_route.resize(route_size);
151 4 MPI_Recv(full_route.data(), route_size, MPI_INT, source, static_cast<int>(Tags::kRoute), MPI_COMM_WORLD,
152 MPI_STATUS_IGNORE);
153 4 }
154
155 18 bool LukinIThorTopologyMPI::HandleTrivial(int &message_len, std::vector<int> &message, int proc_count) {
156
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
18 if (start_ == end_) {
157 10 MPI_Bcast(&message_len, 1, MPI_INT, end_, MPI_COMM_WORLD);
158 10 message.resize(message_len);
159 10 MPI_Bcast(message.data(), message_len, MPI_INT, end_, MPI_COMM_WORLD);
160 10 GetOutput() = std::make_tuple(std::vector<int>{}, message);
161 10 return true;
162 }
163
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (proc_count == 1) {
165 GetOutput() = std::make_tuple(std::vector<int>{}, message);
166 return true;
167 }
168
169 return false;
170 }
171
172 8 void LukinIThorTopologyMPI::InitTopology(int &cols, int &rows, int proc_count) {
173
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (rows = static_cast<int>(std::sqrt(static_cast<double>(proc_count))); rows > 0; rows--) {
174
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (proc_count % rows == 0) {
175 8 cols = proc_count / rows;
176 8 break;
177 }
178 }
179 8 }
180
181 } // namespace lukin_i_torus_topology
182