GCC Code Coverage Report


Directory: ./
File: tasks/sizov_d_bubble_sort/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 80 81 98.8%
Functions: 9 9 100.0%
Branches: 59 80 73.8%

Line Branch Exec Source
1 #include "sizov_d_bubble_sort/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <utility>
7 #include <vector>
8
9 #include "sizov_d_bubble_sort/common/include/common.hpp"
10
11 namespace sizov_d_bubble_sort {
12
13 namespace {
14
15 struct ScatterPlan {
16 std::vector<int> counts;
17 std::vector<int> displs;
18 };
19
20 78 ScatterPlan MakeScatterPlan(int n, int comm_size) {
21 78 ScatterPlan plan;
22
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 plan.counts.assign(comm_size, 0);
23
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 plan.displs.assign(comm_size, 0);
24
25 78 const int base = n / comm_size;
26 78 const int rem = n % comm_size;
27
28 int offset = 0;
29
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 78 times.
234 for (int rank_idx = 0; rank_idx < comm_size; ++rank_idx) {
30
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 50 times.
262 plan.counts[rank_idx] = base + ((rank_idx < rem) ? 1 : 0);
31 156 plan.displs[rank_idx] = offset;
32 156 offset += plan.counts[rank_idx];
33 }
34
35 78 return plan;
36 }
37
38 inline void CompareSwap(int &a, int &b) {
39
2/2
✓ Branch 0 taken 1663 times.
✓ Branch 1 taken 1745 times.
3408 if (a > b) {
40 std::swap(a, b);
41 }
42 }
43
44
2/2
✓ Branch 0 taken 843 times.
✓ Branch 1 taken 7 times.
850 void LocalOddEvenPhase(std::vector<int> &local, int global_offset, int phase_parity) {
45 850 const int local_n = static_cast<int>(local.size());
46
2/2
✓ Branch 0 taken 843 times.
✓ Branch 1 taken 7 times.
850 if (local_n < 2) {
47 return;
48 }
49
50 843 int idx = ((global_offset & 1) == phase_parity) ? 0 : 1;
51
2/2
✓ Branch 0 taken 3408 times.
✓ Branch 1 taken 843 times.
4251 for (; idx + 1 < local_n; idx += 2) {
52
2/2
✓ Branch 0 taken 1663 times.
✓ Branch 1 taken 1745 times.
3408 CompareSwap(local[idx], local[idx + 1]);
53 }
54 }
55
56
1/2
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
850 void ExchangeRightIfNeeded(std::vector<int> &local, const ScatterPlan &plan, int rank, int comm_size, int phase_parity,
57 int tag) {
58
1/2
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
850 if (local.empty()) {
59 636 return;
60 }
61
3/4
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 425 times.
✗ Branch 3 not taken.
850 if (rank + 1 >= comm_size || plan.counts[rank + 1] == 0) {
62 return;
63 }
64
65
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 211 times.
425 const int last_global = plan.displs[rank] + static_cast<int>(local.size()) - 1;
66
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 211 times.
425 if ((last_global & 1) != phase_parity) {
67 return;
68 }
69
70 214 int send_val = local.back();
71 214 int recv_val = 0;
72
73 214 MPI_Sendrecv(&send_val, 1, MPI_INT, rank + 1, tag, &recv_val, 1, MPI_INT, rank + 1, tag, MPI_COMM_WORLD,
74 MPI_STATUS_IGNORE);
75
76 214 local.back() = std::min(send_val, recv_val);
77 }
78
79
1/2
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
850 void ExchangeLeftIfNeeded(std::vector<int> &local, const ScatterPlan &plan, int rank, int phase_parity, int tag) {
80
1/2
✓ Branch 0 taken 850 times.
✗ Branch 1 not taken.
850 if (local.empty()) {
81 636 return;
82 }
83
3/4
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 425 times.
✗ Branch 3 not taken.
850 if (rank - 1 < 0 || plan.counts[rank - 1] == 0) {
84 return;
85 }
86
87
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 211 times.
425 const int first_global = plan.displs[rank];
88 425 const int boundary_left_global = first_global - 1;
89
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 211 times.
425 if ((boundary_left_global & 1) != phase_parity) {
90 return;
91 }
92
93 214 int send_val = local.front();
94 214 int recv_val = 0;
95
96 214 MPI_Sendrecv(&send_val, 1, MPI_INT, rank - 1, tag, &recv_val, 1, MPI_INT, rank - 1, tag, MPI_COMM_WORLD,
97 MPI_STATUS_IGNORE);
98
99 214 local.front() = std::max(send_val, recv_val);
100 }
101
102 } // namespace
103
104
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 SizovDBubbleSortMPI::SizovDBubbleSortMPI(const InType &in) {
105 SetTypeOfTask(GetStaticTypeOfTask());
106
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 GetInput() = in;
107 GetOutput().clear();
108 80 }
109
110 80 bool SizovDBubbleSortMPI::ValidationImpl() {
111 80 int rank = 0;
112 80 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
113
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
80 if (rank == 0) {
114 40 return !GetInput().empty();
115 }
116 return true;
117 }
118
119 80 bool SizovDBubbleSortMPI::PreProcessingImpl() {
120 80 data_ = GetInput();
121 80 return true;
122 }
123
124 80 bool SizovDBubbleSortMPI::RunImpl() {
125 80 int rank = 0;
126 80 int comm_size = 1;
127 80 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
128 80 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
129
130 80 int n = 0;
131
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
80 if (rank == 0) {
132 40 n = static_cast<int>(data_.size());
133 }
134 80 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
135
136
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
80 if (n <= 1) {
137
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (rank != 0) {
138 1 data_.assign(n, 0);
139 }
140
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (n == 1) {
141 2 MPI_Bcast(data_.data(), 1, MPI_INT, 0, MPI_COMM_WORLD);
142 }
143 2 GetOutput() = data_;
144 2 return true;
145 }
146
147 78 const ScatterPlan plan = MakeScatterPlan(n, comm_size);
148
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 const int local_n = plan.counts[rank];
149
150
3/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
✓ Branch 4 taken 39 times.
78 std::vector<int> local(local_n);
151
3/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 39 times.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
117 MPI_Scatterv(rank == 0 ? data_.data() : nullptr, plan.counts.data(), plan.displs.data(), MPI_INT, local.data(),
152 local_n, MPI_INT, 0, MPI_COMM_WORLD);
153
154
2/2
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 78 times.
928 for (int phase = 0; phase < n; ++phase) {
155 850 const int parity = phase & 1;
156 const int tag = phase;
157
158 850 LocalOddEvenPhase(local, plan.displs[rank], parity);
159
1/2
✓ Branch 1 taken 850 times.
✗ Branch 2 not taken.
850 ExchangeRightIfNeeded(local, plan, rank, comm_size, parity, tag);
160
1/2
✓ Branch 1 taken 850 times.
✗ Branch 2 not taken.
850 ExchangeLeftIfNeeded(local, plan, rank, parity, tag);
161 }
162
163
2/6
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
78 std::vector<int> result(n);
164
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 MPI_Allgatherv(local.data(), local_n, MPI_INT, result.data(), plan.counts.data(), plan.displs.data(), MPI_INT,
165 MPI_COMM_WORLD);
166
167 GetOutput() = std::move(result);
168 return true;
169 78 }
170
171 80 bool SizovDBubbleSortMPI::PostProcessingImpl() {
172 80 return true;
173 }
174
175 } // namespace sizov_d_bubble_sort
176