GCC Code Coverage Report


Directory: ./
File: tasks/kutergin_a_closest_pair/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 58 60 96.7%
Functions: 6 6 100.0%
Branches: 38 48 79.2%

Line Branch Exec Source
1 #include "kutergin_a_closest_pair/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <limits>
8 #include <vector>
9
10 #include "kutergin_a_closest_pair/common/include/common.hpp"
11
12 namespace kutergin_a_closest_pair {
13
14
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 KuterginAClosestPairMPI::KuterginAClosestPairMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput() = in;
17 20 GetOutput() = -1;
18 20 }
19
20 20 bool KuterginAClosestPairMPI::ValidationImpl() {
21 20 return true;
22 }
23
24 20 bool KuterginAClosestPairMPI::PreProcessingImpl() {
25 20 return true;
26 }
27
28 namespace {
29
30 16 std::vector<int> DistributeData(int rank, int size, int n, const std::vector<int> &v) {
31 16 int local_size = n / size;
32 16 int remainder = n % size;
33
34
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 int start = (rank * local_size) + std::min(rank, remainder);
35
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 int end = start + local_size + (rank < remainder ? 1 : 0);
36
37
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank == size - 1) {
38 end = n;
39 }
40
41 16 std::vector<int> local_data(end - start);
42
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank == 0) {
43 8 std::copy(v.begin() + start, v.begin() + end, local_data.begin());
44
45
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for (int i = 1; i < size; ++i) {
46
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 int other_start = (i * local_size) + std::min(i, remainder);
47
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 int other_end = other_start + local_size + (i < remainder ? 1 : 0);
48
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (i == size - 1) {
49 other_end = n;
50 }
51
52
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Send(v.data() + other_start, other_end - other_start, MPI_INT, i, 0, MPI_COMM_WORLD);
53 }
54 } else {
55
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Recv(local_data.data(), static_cast<int>(local_data.size()), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
56 }
57
58 16 return local_data;
59 }
60
61 int FindLocalMin(const std::vector<int> &local_data, int start_idx, int &found_idx) {
62 int local_min = std::numeric_limits<int>::max();
63 found_idx = -1;
64
65
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 16 times.
34 for (int i = 0; i < static_cast<int>(local_data.size()) - 1; ++i) {
66
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 int diff = std::abs(local_data[i + 1] - local_data[i]);
67
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (diff < local_min) {
68 local_min = diff;
69 16 found_idx = start_idx + i;
70 }
71 }
72
73 return local_min;
74 }
75
76 int CalculateStartIndex(int rank, int size, int n) {
77 16 int local_size = n / size;
78 16 int remainder = n % size;
79 16 return (rank * local_size) + std::min(rank, remainder);
80 }
81
82 int CalculateEndIndex(int rank, int size, int n) {
83 int local_size = n / size;
84 int remainder = n % size;
85
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 int end = CalculateStartIndex(rank, size, n) + local_size + (rank < remainder ? 1 : 0);
86
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank == size - 1) {
87 end = n;
88 }
89 return end;
90 }
91
92 int CheckBoundary(int rank, int size, int end, int n, const std::vector<int> &v, const std::vector<int> &local_data,
93 int current_min, int &current_idx) {
94
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
16 if (rank < size - 1 && end < n) {
95
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 int boundary_diff = std::abs(v[end] - local_data.back());
96
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (boundary_diff < current_min) {
97 current_min = boundary_diff;
98 4 current_idx = end - 1;
99 }
100 }
101 return current_min;
102 }
103
104 } // namespace
105
106 20 bool KuterginAClosestPairMPI::RunImpl() {
107 20 int rank = 0;
108 20 int size = 0;
109 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
110 20 MPI_Comm_size(MPI_COMM_WORLD, &size);
111
112 const auto &v = GetInput();
113 20 int n = static_cast<int>(v.size());
114
115 20 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
116
117
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 if (n < 2) {
118 4 GetOutput() = -1;
119 4 return true;
120 }
121
122 16 auto local_data = DistributeData(rank, size, n, v);
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (local_data.empty()) {
124 GetOutput() = -1;
125 return true;
126 }
127
128 16 int start_idx = CalculateStartIndex(rank, size, n);
129 int local_idx = -1;
130 int local_min = FindLocalMin(local_data, start_idx, local_idx);
131
132 int end = CalculateEndIndex(rank, size, n);
133 local_min = CheckBoundary(rank, size, end, n, v, local_data, local_min, local_idx);
134
135 struct MinIndex {
136 int val = 0;
137 int idx = -1;
138 };
139
140 MinIndex local_result;
141 16 local_result.val = local_min;
142 16 local_result.idx = local_idx;
143
144 16 MinIndex global_result;
145
146
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Allreduce(&local_result, &global_result, 1, MPI_2INT, MPI_MINLOC, MPI_COMM_WORLD);
147
148 16 GetOutput() = global_result.idx;
149 16 return true;
150 }
151
152 20 bool KuterginAClosestPairMPI::PostProcessingImpl() {
153 20 return true;
154 }
155
156 } // namespace kutergin_a_closest_pair
157