GCC Code Coverage Report


Directory: ./
File: tasks/borunov_v_ring/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 78 85 91.8%
Functions: 8 8 100.0%
Branches: 30 56 53.6%

Line Branch Exec Source
1 #include "borunov_v_ring/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <chrono>
6 #include <cmath>
7 #include <cstddef>
8 #include <utility>
9 #include <vector>
10
11 #include "borunov_v_ring/common/include/common.hpp"
12
13 namespace borunov_v_ring {
14
15 10 BorunovVRingMPI::BorunovVRingMPI(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 10 GetInput() = in;
18 10 }
19
20 10 bool BorunovVRingMPI::ValidationImpl() {
21 10 int initialized = 0;
22 10 MPI_Initialized(&initialized);
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (initialized == 0) {
24 return (GetInput().source_rank >= 0 && GetInput().target_rank >= 0);
25 }
26
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 return (GetInput().source_rank >= 0 && GetInput().target_rank >= 0);
27 }
28
29 10 bool BorunovVRingMPI::PreProcessingImpl() {
30 10 return true;
31 }
32 namespace {
33 7 inline void AddDelay() {
34 7 auto start_time = std::chrono::steady_clock::now();
35 auto target_duration = std::chrono::milliseconds(200);
36
37 7 volatile double sum = 0.0;
38 const int iterations = 10000;
39
40
2/2
✓ Branch 1 taken 8328 times.
✓ Branch 2 taken 7 times.
8335 while (std::chrono::steady_clock::now() - start_time < target_duration) {
41
2/2
✓ Branch 0 taken 83280000 times.
✓ Branch 1 taken 8328 times.
83288328 for (int i = 0; i < iterations; ++i) {
42 83280000 sum += std::sin(static_cast<double>(i));
43 }
44 }
45 7 (void)sum;
46 7 }
47
48 bool ComputeIsParticipant(int ring_rank, int source, int target) {
49 10 if (source == target) {
50 6 return ring_rank == source;
51 }
52
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (source < target) {
53 2 return (ring_rank >= source && ring_rank <= target);
54 }
55 2 return (ring_rank >= source || ring_rank <= target);
56 }
57
58 5 void HandleSource(BorunovVRingMPI *self, MPI_Comm ring_comm, int ring_rank, int next_rank, int target, int data) {
59
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 std::vector<int> path_history;
60 path_history.push_back(ring_rank);
61 5 AddDelay();
62
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (ring_rank == target) {
63 self->GetOutput() = std::move(path_history);
64 return;
65 }
66 2 int path_size = static_cast<int>(path_history.size());
67
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Send(&path_size, 1, MPI_INT, next_rank, 0, ring_comm);
68
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (path_size > 0) {
69
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Send(path_history.data(), path_size, MPI_INT, next_rank, 1, ring_comm);
70 }
71
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Send(&data, 1, MPI_INT, next_rank, 2, ring_comm);
72 }
73
74 2 void HandleParticipant(BorunovVRingMPI *self, MPI_Comm ring_comm, int prev_rank, int next_rank, int ring_rank,
75 int target) {
76 2 int path_size = 0;
77 MPI_Status status;
78 2 MPI_Recv(&path_size, 1, MPI_INT, prev_rank, 0, ring_comm, &status);
79 2 int comm_size = 0;
80 2 MPI_Comm_size(ring_comm, &comm_size);
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (path_size < 0) {
82 path_size = 0;
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (path_size > comm_size) {
84 path_size = comm_size;
85 }
86 2 std::vector<int> path_history(static_cast<std::size_t>(path_size));
87
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (path_size > 0) {
88
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Recv(path_history.data(), path_size, MPI_INT, prev_rank, 1, ring_comm, &status);
89 }
90 2 int received_data = 0;
91
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Recv(&received_data, 1, MPI_INT, prev_rank, 2, ring_comm, &status);
92 2 AddDelay();
93 path_history.push_back(ring_rank);
94
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ring_rank == target) {
95
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 self->GetOutput() = path_history;
96 return;
97 }
98 path_size = static_cast<int>(path_history.size());
99 MPI_Send(&path_size, 1, MPI_INT, next_rank, 0, ring_comm);
100 MPI_Send(path_history.data(), path_size, MPI_INT, next_rank, 1, ring_comm);
101 MPI_Send(&received_data, 1, MPI_INT, next_rank, 2, ring_comm);
102 }
103 } // namespace
104
105 10 bool BorunovVRingMPI::RunImpl() {
106 10 int world_rank = 0;
107 10 int world_size = 0;
108 10 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
109 10 MPI_Comm_size(MPI_COMM_WORLD, &world_size);
110
111 const auto &input = GetInput();
112 10 int source = input.source_rank;
113 10 int target = input.target_rank;
114
115
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (world_size > 0) {
116 10 source = source % world_size;
117 10 target = target % world_size;
118 }
119
120 10 MPI_Group world_group = MPI_GROUP_NULL;
121 10 MPI_Comm_group(MPI_COMM_WORLD, &world_group);
122 10 MPI_Comm ring_comm = MPI_COMM_WORLD;
123 10 MPI_Comm_dup(MPI_COMM_WORLD, &ring_comm);
124
125 10 int ring_rank = 0;
126 10 int ring_size = 0;
127 10 MPI_Comm_rank(ring_comm, &ring_rank);
128 10 MPI_Comm_size(ring_comm, &ring_size);
129
130 10 int next_rank = (ring_rank + 1) % ring_size;
131 10 int prev_rank = (ring_rank - 1 + ring_size) % ring_size;
132
133 10 MPI_Group_free(&world_group);
134
135
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 bool is_participant = ComputeIsParticipant(ring_rank, source, target);
136
137
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (ring_rank == source) {
138 5 HandleSource(this, ring_comm, ring_rank, next_rank, target, input.data);
139
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 } else if (is_participant) {
140 2 HandleParticipant(this, ring_comm, prev_rank, next_rank, ring_rank, target);
141 } else {
142 }
143
144 10 MPI_Barrier(ring_comm);
145 10 MPI_Comm_free(&ring_comm);
146 10 return true;
147 }
148
149 10 bool BorunovVRingMPI::PostProcessingImpl() {
150 10 return true;
151 }
152
153 } // namespace borunov_v_ring
154