GCC Code Coverage Report


Directory: ./
File: tasks/lazareva_a_torus_grid/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 86 93 92.5%
Functions: 9 11 81.8%
Branches: 39 74 52.7%

Line Branch Exec Source
1 #include "lazareva_a_torus_grid/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <iterator>
8 #include <utility>
9 #include <vector>
10
11 #include "lazareva_a_torus_grid/common/include/common.hpp"
12
13 namespace lazareva_a_torus_grid {
14
15
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 LazarevaATorusGridMPI::LazarevaATorusGridMPI(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput() = in;
18 GetOutput() = {};
19 20 }
20
21 20 bool LazarevaATorusGridMPI::ValidationImpl() {
22 20 int mpi_initialized = 0;
23 20 MPI_Initialized(&mpi_initialized);
24
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (mpi_initialized == 0) {
25 return false;
26 }
27
28 20 MPI_Comm_size(MPI_COMM_WORLD, &world_size_);
29 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
30
31 20 int is_valid = 0;
32
33
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank_ == 0) {
34 const auto &input = GetInput();
35
36
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (input.size() >= 3) {
37 10 int source = input[0];
38 10 int dest = input[1];
39
4/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
10 is_valid = static_cast<int>(source >= 0 && source < world_size_ && dest >= 0 && dest < world_size_);
40 }
41 }
42
43 20 MPI_Bcast(&is_valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
44
45 20 return is_valid != 0;
46 }
47
48 20 bool LazarevaATorusGridMPI::PreProcessingImpl() {
49 20 MPI_Comm_size(MPI_COMM_WORLD, &world_size_);
50 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
51
52 20 rows_ = static_cast<int>(std::sqrt(static_cast<double>(world_size_)));
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 while (world_size_ % rows_ != 0) {
54 rows_--;
55 }
56 20 cols_ = world_size_ / rows_;
57
58 20 return true;
59 }
60
61 int LazarevaATorusGridMPI::CoordsToRank(int row, int col) const {
62 10 row = ((row % rows_) + rows_) % rows_;
63 10 col = ((col % cols_) + cols_) % cols_;
64 10 return (row * cols_) + col;
65 }
66
67 int LazarevaATorusGridMPI::ShortestDirection(int from, int to, int size) {
68 10 int forward = ((to - from) + size) % size;
69 10 int backward = ((from - to) + size) % size;
70
71
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 return (forward <= backward) ? 1 : -1;
72 }
73
74 10 int LazarevaATorusGridMPI::ComputeNextNode(int current, int dest) const {
75
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (current == dest) {
76 return -1;
77 }
78
79 10 int curr_row = current / cols_;
80 10 int curr_col = current % cols_;
81 10 int dest_row = dest / cols_;
82 10 int dest_col = dest % cols_;
83
84
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (curr_col != dest_col) {
85 int dir = ShortestDirection(curr_col, dest_col, cols_);
86 10 return CoordsToRank(curr_row, curr_col + dir);
87 }
88
89 if (curr_row != dest_row) {
90 int dir = ShortestDirection(curr_row, dest_row, rows_);
91 return CoordsToRank(curr_row + dir, curr_col);
92 }
93
94 return -1;
95 }
96
97 20 std::vector<int> LazarevaATorusGridMPI::ComputeFullPath(int source, int dest) const {
98
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<int> path;
99 path.push_back(source);
100
101 20 int current = source;
102
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 20 times.
30 while (current != dest) {
103 10 int next = ComputeNextNode(current, dest);
104
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (next == -1) {
105 break;
106 }
107 path.push_back(next);
108 current = next;
109 }
110
111 20 return path;
112 }
113
114 5 void LazarevaATorusGridMPI::SendData(const std::vector<int> &data, int dest_node) {
115 5 int data_size = static_cast<int>(data.size());
116 5 MPI_Send(&data_size, 1, MPI_INT, dest_node, 0, MPI_COMM_WORLD);
117
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (data_size > 0) {
118 5 MPI_Send(data.data(), data_size, MPI_INT, dest_node, 1, MPI_COMM_WORLD);
119 }
120 5 }
121
122 5 std::vector<int> LazarevaATorusGridMPI::ReceiveData(int source_node) {
123 5 int recv_size = 0;
124 5 MPI_Recv(&recv_size, 1, MPI_INT, source_node, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
125 5 std::vector<int> recv_data;
126
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (recv_size > 0) {
127
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 recv_data.resize(recv_size);
128
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 MPI_Recv(recv_data.data(), recv_size, MPI_INT, source_node, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
129 }
130 5 return recv_data;
131 }
132
133 20 bool LazarevaATorusGridMPI::RunImpl() {
134 20 int source = 0;
135 20 int dest = 0;
136
137
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank_ == 0) {
138 const auto &input = GetInput();
139 10 source = input[0];
140 10 dest = input[1];
141 }
142
143 20 MPI_Bcast(&source, 1, MPI_INT, 0, MPI_COMM_WORLD);
144 20 MPI_Bcast(&dest, 1, MPI_INT, 0, MPI_COMM_WORLD);
145
146 20 std::vector<int> path = ComputeFullPath(source, dest);
147 20 int path_size = static_cast<int>(path.size());
148
149 auto it = std::ranges::find(path, rank_);
150 bool on_path = (it != path.end());
151
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 int my_index = on_path ? static_cast<int>(std::distance(path.begin(), it)) : -1;
152
153 20 std::vector<int> recv_data;
154
155
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (source == dest) {
156
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank_ == source) {
157 const auto &input = GetInput();
158 5 recv_data.assign(input.begin() + 2, input.end());
159 }
160
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 } else if (rank_ == source) {
161 const auto &input = GetInput();
162 5 recv_data.assign(input.begin() + 2, input.end());
163
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 SendData(recv_data, path[1]);
164
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (on_path) {
165
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 int prev_node = path[my_index - 1];
166
1/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
5 recv_data = ReceiveData(prev_node);
167
168
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (rank_ != dest && (my_index + 1) < path_size) {
169 SendData(recv_data, path[my_index + 1]);
170 }
171 }
172
173
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank_ == dest) {
174 GetOutput() = std::move(recv_data);
175 GetOutput().push_back(path_size);
176 10 GetOutput().insert(GetOutput().end(), path.begin(), path.end());
177 } else {
178 GetOutput().clear();
179 }
180
181 20 return true;
182 }
183
184 20 bool LazarevaATorusGridMPI::PostProcessingImpl() {
185 20 return true;
186 }
187
188 } // namespace lazareva_a_torus_grid
189