GCC Code Coverage Report


Directory: ./
File: tasks/nikitin_a_buble_sort/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 71 71 100.0%
Functions: 8 8 100.0%
Branches: 58 82 70.7%

Line Branch Exec Source
1 #include "nikitin_a_buble_sort/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <utility>
7 #include <vector>
8
9 #include "nikitin_a_buble_sort/common/include/common.hpp"
10
11 namespace nikitin_a_buble_sort {
12
13
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 NikitinABubleSortMPI::NikitinABubleSortMPI(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 GetInput() = in;
16 GetOutput().clear();
17 42 }
18
19 42 bool NikitinABubleSortMPI::ValidationImpl() {
20 42 return true;
21 }
22
23 42 bool NikitinABubleSortMPI::PreProcessingImpl() {
24 42 data_ = GetInput();
25 42 return true;
26 }
27
28 42 bool NikitinABubleSortMPI::RunImpl() {
29 42 int rank = 0;
30 42 int comm_size = 0;
31 42 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
32 42 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
33
34
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
42 if (rank == 0) {
35 21 n_ = static_cast<int>(data_.size());
36 }
37 42 MPI_Bcast(&n_, 1, MPI_INT, 0, MPI_COMM_WORLD);
38
39
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 if (n_ <= 1) {
40 4 std::vector<double> result;
41
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (n_ == 1) {
42
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 result.resize(1);
43
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (rank == 0) {
44 1 result[0] = data_[0];
45 }
46
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 MPI_Bcast(result.data(), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
47 }
48 GetOutput() = std::move(result);
49 return true;
50 }
51
52 38 const int base = n_ / comm_size;
53 38 const int rem = n_ % comm_size;
54
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 7 times.
38 const int count = base + (rank < rem ? 1 : 0);
55 38 const int offset = (rank * base) + std::min(rank, rem);
56
57 38 std::vector<int> counts(comm_size);
58
1/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
38 std::vector<int> displs(comm_size);
59 int current_offset = 0;
60
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 38 times.
114 for (int i = 0; i < comm_size; ++i) {
61
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 14 times.
138 counts[i] = base + (i < rem ? 1 : 0);
62 76 displs[i] = current_offset;
63 76 current_offset += counts[i];
64 }
65
66
3/6
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
38 std::vector<double> local(count);
67
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 38 times.
✗ Branch 4 not taken.
57 MPI_Scatterv(rank == 0 ? data_.data() : nullptr, counts.data(), displs.data(), MPI_DOUBLE, local.data(), count,
68 MPI_DOUBLE, 0, MPI_COMM_WORLD);
69
70
2/2
✓ Branch 0 taken 3410 times.
✓ Branch 1 taken 38 times.
3448 for (int phase = 0; phase < n_; ++phase) {
71 3410 const int parity = phase & 1;
72 const int tag = phase;
73
74 3410 LocalSort(local, offset, parity);
75
1/2
✓ Branch 1 taken 3410 times.
✗ Branch 2 not taken.
3410 ExchangeRight(local, counts, displs, rank, comm_size, parity, tag);
76
1/2
✓ Branch 1 taken 3410 times.
✗ Branch 2 not taken.
3410 ExchangeLeft(local, counts, displs, rank, parity, tag);
77 }
78
79
2/6
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
38 std::vector<double> result(n_);
80
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 MPI_Allgatherv(local.data(), count, MPI_DOUBLE, result.data(), counts.data(), displs.data(), MPI_DOUBLE,
81 MPI_COMM_WORLD);
82
83 GetOutput() = std::move(result);
84 return true;
85 }
86
87 42 bool NikitinABubleSortMPI::PostProcessingImpl() {
88 42 return true;
89 }
90
91
2/2
✓ Branch 0 taken 3406 times.
✓ Branch 1 taken 4 times.
3410 void NikitinABubleSortMPI::LocalSort(std::vector<double> &local, int global_offset, int phase_parity) {
92 3410 const int local_n = static_cast<int>(local.size());
93
2/2
✓ Branch 0 taken 3406 times.
✓ Branch 1 taken 4 times.
3410 if (local_n < 2) {
94 return;
95 }
96
97 3406 int start = ((global_offset & 1) == phase_parity) ? 0 : 1;
98
2/2
✓ Branch 0 taken 628681 times.
✓ Branch 1 taken 3406 times.
632087 for (int i = start; i + 1 < local_n; i += 2) {
99
2/2
✓ Branch 0 taken 314361 times.
✓ Branch 1 taken 314320 times.
628681 if (local[i] > local[i + 1]) {
100 std::swap(local[i], local[i + 1]);
101 }
102 }
103 }
104
105
1/2
✓ Branch 0 taken 3410 times.
✗ Branch 1 not taken.
3410 void NikitinABubleSortMPI::ExchangeRight(std::vector<double> &local, const std::vector<int> &counts,
106 const std::vector<int> &displs, int rank, int comm_size, int phase_parity,
107 int tag) {
108
1/2
✓ Branch 0 taken 3410 times.
✗ Branch 1 not taken.
3410 if (local.empty()) {
109 2554 return;
110 }
111
112
3/4
✓ Branch 0 taken 1705 times.
✓ Branch 1 taken 1705 times.
✓ Branch 2 taken 1705 times.
✗ Branch 3 not taken.
3410 if (rank + 1 >= comm_size || counts[rank + 1] == 0) {
113 return;
114 }
115
116
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 849 times.
1705 const int last_global = displs[rank] + static_cast<int>(local.size()) - 1;
117
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 849 times.
1705 if ((last_global & 1) != phase_parity) {
118 return;
119 }
120
121 856 double send_val = local.back();
122 856 double recv_val = 0;
123
124 856 MPI_Sendrecv(&send_val, 1, MPI_DOUBLE, rank + 1, tag, &recv_val, 1, MPI_DOUBLE, rank + 1, tag, MPI_COMM_WORLD,
125 MPI_STATUS_IGNORE);
126
127 856 local.back() = std::min(send_val, recv_val);
128 }
129
130
1/2
✓ Branch 0 taken 3410 times.
✗ Branch 1 not taken.
3410 void NikitinABubleSortMPI::ExchangeLeft(std::vector<double> &local, const std::vector<int> &counts,
131 const std::vector<int> &displs, int rank, int phase_parity, int tag) {
132
1/2
✓ Branch 0 taken 3410 times.
✗ Branch 1 not taken.
3410 if (local.empty()) {
133 2554 return;
134 }
135
3/4
✓ Branch 0 taken 1705 times.
✓ Branch 1 taken 1705 times.
✓ Branch 2 taken 1705 times.
✗ Branch 3 not taken.
3410 if (rank - 1 < 0 || counts[rank - 1] == 0) {
136 return;
137 }
138
139
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 849 times.
1705 const int first_global = displs[rank];
140 1705 const int boundary_left_global = first_global - 1;
141
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 849 times.
1705 if ((boundary_left_global & 1) != phase_parity) {
142 return;
143 }
144
145 856 double send_val = local.front();
146 856 double recv_val = 0;
147
148 856 MPI_Sendrecv(&send_val, 1, MPI_DOUBLE, rank - 1, tag, &recv_val, 1, MPI_DOUBLE, rank - 1, tag, MPI_COMM_WORLD,
149 MPI_STATUS_IGNORE);
150
151 856 local.front() = std::max(send_val, recv_val);
152 }
153
154 } // namespace nikitin_a_buble_sort
155