GCC Code Coverage Report


Directory: ./
File: tasks/otcheskov_s_linear_topology/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 63 64 98.4%
Functions: 8 8 100.0%
Branches: 56 86 65.1%

Line Branch Exec Source
1 #include "otcheskov_s_linear_topology/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstddef>
6 #include <utility>
7 #include <vector>
8
9 #include "otcheskov_s_linear_topology/common/include/common.hpp"
10
11 namespace otcheskov_s_linear_topology {
12
13 namespace {
14 constexpr int kMessageTag = 100;
15 constexpr int kConfirmTag = 200;
16 constexpr int kDataTagOffset = 1;
17 } // namespace
18
19
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 OtcheskovSLinearTopologyMPI::OtcheskovSLinearTopologyMPI(const InType &in) {
20 SetTypeOfTask(GetStaticTypeOfTask());
21
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank_);
22
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Comm_size(MPI_COMM_WORLD, &proc_num_);
23
24 GetInput() = in;
25
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (proc_rank_ != in.first.src) {
26 GetInput().second.clear();
27 GetInput().second.shrink_to_fit();
28 }
29 20 }
30
31 20 bool OtcheskovSLinearTopologyMPI::ValidationImpl() {
32 const auto &[header, data] = GetInput();
33
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (header.src < 0 || header.src >= proc_num_) {
34 return false;
35 }
36
37 20 bool is_valid = false;
38
39
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (proc_rank_ == header.src) {
40
6/10
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
16 is_valid = (header.dest >= 0 && header.dest < proc_num_ && header.delivered == 0 && !data.empty() &&
41
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 static_cast<size_t>(header.data_size) == data.size());
42 }
43 20 MPI_Bcast(&is_valid, 1, MPI_C_BOOL, GetInput().first.src, MPI_COMM_WORLD);
44 20 return is_valid;
45 }
46
47 20 bool OtcheskovSLinearTopologyMPI::PreProcessingImpl() {
48 20 return true;
49 }
50
51 4 Message OtcheskovSLinearTopologyMPI::ForwardMessageToDest(const Message &initial_msg, int prev, int next, bool is_src,
52 bool is_dest) {
53
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 Message current_msg;
54 auto &[header, data] = current_msg;
55
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!is_src) {
56
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Recv(&header, sizeof(MessageHeader), MPI_BYTE, prev, kMessageTag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
57
58
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 data.resize(header.data_size);
59
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Recv(data.data(), header.data_size, MPI_INT, prev, kMessageTag + kDataTagOffset, MPI_COMM_WORLD,
60 MPI_STATUS_IGNORE);
61 } else {
62 current_msg = initial_msg;
63 }
64
65
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!is_dest) {
66
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Send(&header, sizeof(MessageHeader), MPI_BYTE, next, kMessageTag, MPI_COMM_WORLD);
67
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Send(data.data(), header.data_size, MPI_INT, next, kMessageTag + kDataTagOffset, MPI_COMM_WORLD);
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!is_src) {
69 data.clear();
70 data.shrink_to_fit();
71 }
72 } else {
73 2 header.delivered = 1;
74 }
75 4 return current_msg;
76 }
77
78 4 Message OtcheskovSLinearTopologyMPI::HandleConfirmToSource(Message &current_msg, int prev, int next, bool is_src,
79 bool is_dest) {
80 4 auto &confirm_header = current_msg.first;
81
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (is_dest) {
82 2 MPI_Send(&confirm_header, sizeof(MessageHeader), MPI_BYTE, prev, kConfirmTag, MPI_COMM_WORLD);
83 } else {
84 2 MPI_Recv(&confirm_header, sizeof(MessageHeader), MPI_BYTE, next, kConfirmTag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!is_src) {
86 MPI_Send(&confirm_header, sizeof(MessageHeader), MPI_BYTE, prev, kConfirmTag, MPI_COMM_WORLD);
87 }
88 }
89 4 return current_msg;
90 }
91
92 20 Message OtcheskovSLinearTopologyMPI::SendMessageLinear(const Message &msg) const {
93 auto [header, data] = msg;
94 20 header.delivered = 0;
95
96
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 if (header.src == header.dest) {
97 16 header.delivered = 1;
98 return {header, std::move(data)};
99 }
100
101
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 const int direction = (header.dest > header.src) ? 1 : -1;
102
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 const bool should_participate = (direction > 0 && proc_rank_ >= header.src && proc_rank_ <= header.dest) ||
103
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 (direction < 0 && proc_rank_ <= header.src && proc_rank_ >= header.dest);
104
105 if (!should_participate) {
106 return {MessageHeader(), MessageData()};
107 }
108
109 4 const bool is_src = (proc_rank_ == header.src);
110 4 const bool is_dest = (proc_rank_ == header.dest);
111
112
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 const int prev = is_src ? MPI_PROC_NULL : proc_rank_ - direction;
113
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 const int next = is_dest ? MPI_PROC_NULL : proc_rank_ + direction;
114
115
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Message current_msg = ForwardMessageToDest({header, std::move(data)}, prev, next, is_src, is_dest);
116 // пересылка подтверждения
117
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return HandleConfirmToSource(current_msg, prev, next, is_src, is_dest);
118 }
119
120 20 bool OtcheskovSLinearTopologyMPI::RunImpl() {
121 const auto &in_header = GetInput().first;
122 20 const int src = in_header.src;
123 20 const int dest = in_header.dest;
124
125
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (src < 0 || src >= proc_num_) {
126 return false;
127 }
128
129 MessageHeader msg_header;
130 msg_header.src = src;
131 msg_header.dest = dest;
132 msg_header.delivered = 0;
133 msg_header.data_size = 0;
134
135 20 MessageData data;
136
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (proc_rank_ == src) {
137
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 data = GetInput().second;
138 10 msg_header.data_size = static_cast<int>(data.size());
139 }
140
141
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 Message result_msg = SendMessageLinear({msg_header, data});
142
143 bool check_passed = false;
144
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (proc_rank_ == src) {
145 10 check_passed = result_msg.first.delivered != 0;
146
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 } else if (proc_rank_ == dest) {
147 2 check_passed = !result_msg.second.empty();
148 } else {
149 check_passed = true;
150 }
151 GetOutput() = result_msg;
152
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Barrier(MPI_COMM_WORLD);
153 return check_passed;
154 }
155
156 20 bool OtcheskovSLinearTopologyMPI::PostProcessingImpl() {
157 20 return true;
158 }
159
160 } // namespace otcheskov_s_linear_topology
161