GCC Code Coverage Report


Directory: ./
File: tasks/lazareva_a_gauss_filter_horizontal/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 90 90 100.0%
Functions: 8 8 100.0%
Branches: 61 98 62.2%

Line Branch Exec Source
1 #include "lazareva_a_gauss_filter_horizontal/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstddef>
8 #include <limits>
9 #include <vector>
10
11 #include "lazareva_a_gauss_filter_horizontal/common/include/common.hpp"
12
13 namespace lazareva_a_gauss_filter_horizontal {
14
15 namespace {
16 1410624 int GetKernelValue(int ki, int kj) {
17 1410624 constexpr std::array<std::array<int, 3>, 3> kKernelLocal = {{{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}};
18
2/4
✓ Branch 0 taken 1410624 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1410624 times.
✗ Branch 3 not taken.
1410624 return kKernelLocal.at(ki).at(kj);
19 }
20
21 void ComputeRowDistribution(int height, int size, std::vector<int> &rows_count, std::vector<int> &rows_offset) {
22 10 int rows_per_proc = height / size;
23 10 int remainder = height % size;
24
25 int offset = 0;
26
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int i = 0; i < size; i++) {
27
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 rows_count[i] = rows_per_proc + ((i < remainder) ? 1 : 0);
28 20 rows_offset[i] = offset;
29 20 offset += rows_count[i];
30 }
31 }
32
33 10 void ComputeScatterParams(int height, int width, const std::vector<int> &rows_count,
34 const std::vector<int> &rows_offset, std::vector<int> &sendcounts, std::vector<int> &displs) {
35 10 int size = static_cast<int>(rows_count.size());
36
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int i = 0; i < size; i++) {
37
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 int start = rows_offset[i];
38 20 int count = rows_count[i];
39
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 int htop = (start > 0) ? 1 : 0;
40
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 int hbot = ((start + count) < height) ? 1 : 0;
41
42 20 sendcounts[i] = (count + htop + hbot) * width;
43 20 displs[i] = (start - htop) * width;
44 }
45 10 }
46
47 10 void ApplyGaussianFilter(const std::vector<int> &local_data, std::vector<int> &local_result, int local_rows, int width,
48 int extended_rows, int halo_top) {
49
2/2
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 10 times.
754 for (int i = 0; i < local_rows; i++) {
50 744 int ext_i = i + halo_top;
51
52
2/2
✓ Branch 0 taken 156736 times.
✓ Branch 1 taken 744 times.
157480 for (int j = 0; j < width; j++) {
53 int sum = 0;
54
55
2/2
✓ Branch 0 taken 470208 times.
✓ Branch 1 taken 156736 times.
626944 for (int ki = 0; ki < 3; ki++) {
56
2/2
✓ Branch 0 taken 1410624 times.
✓ Branch 1 taken 470208 times.
1880832 for (int kj = 0; kj < 3; kj++) {
57 1410624 int row = std::clamp(ext_i + ki - 1, 0, extended_rows - 1);
58 1410624 int col = std::clamp(j + kj - 1, 0, width - 1);
59
60 1410624 int pixel_value = local_data[(row * width) + col];
61 1410624 sum += pixel_value * GetKernelValue(ki, kj);
62 }
63 }
64
65 156736 local_result[(i * width) + j] = sum / 16;
66 }
67 }
68 10 }
69 } // namespace
70
71
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 LazarevaAGaussFilterHorizontalMPI::LazarevaAGaussFilterHorizontalMPI(const InType &in) {
72 SetTypeOfTask(GetStaticTypeOfTask());
73
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetInput() = in;
74 GetOutput().clear();
75 10 }
76
77 10 bool LazarevaAGaussFilterHorizontalMPI::ValidationImpl() {
78 10 int rank = 0;
79 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
80
81 10 int is_valid = 0;
82
83
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
84 5 is_valid = static_cast<int>(
85
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
5 (GetInput().size() >= 2) && GetOutput().empty() && (GetInput()[0] > 0) && (GetInput()[1] > 0) &&
86
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
15 (GetInput()[0] <= std::numeric_limits<int>::max() / GetInput()[1]) &&
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 (GetInput().size() == (2 + (static_cast<size_t>(GetInput()[0]) * static_cast<size_t>(GetInput()[1])))));
88 }
89
90 10 MPI_Bcast(&is_valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
91
92 10 return static_cast<bool>(is_valid);
93 }
94
95 10 bool LazarevaAGaussFilterHorizontalMPI::PreProcessingImpl() {
96 10 int rank = 0;
97 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
98
99
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
100 GetOutput().clear();
101 5 height_ = GetInput()[0];
102 5 width_ = GetInput()[1];
103 }
104
105 10 MPI_Bcast(&height_, 1, MPI_INT, 0, MPI_COMM_WORLD);
106 10 MPI_Bcast(&width_, 1, MPI_INT, 0, MPI_COMM_WORLD);
107
108
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
109 5 GetOutput().resize(static_cast<size_t>(height_) * static_cast<size_t>(width_));
110 }
111
112 10 return true;
113 }
114
115 10 bool LazarevaAGaussFilterHorizontalMPI::RunImpl() {
116 10 int rank = 0;
117 10 int size = 0;
118 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
119 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
120
121 10 std::vector<int> rows_count(size);
122
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> rows_offset(size);
123 10 ComputeRowDistribution(height_, size, rows_count, rows_offset);
124
125
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 int local_rows = rows_count[rank];
126 10 int local_start_row = rows_offset[rank];
127
128
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 int halo_top = (local_start_row > 0) ? 1 : 0;
129
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 int halo_bottom = ((local_start_row + local_rows) < height_) ? 1 : 0;
130 10 int extended_rows = local_rows + halo_top + halo_bottom;
131
132
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> sendcounts(size);
133
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> displs(size);
134 10 ComputeScatterParams(height_, width_, rows_count, rows_offset, sendcounts, displs);
135
136
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> local_data(static_cast<size_t>(extended_rows) * static_cast<size_t>(width_));
137
138
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Scatterv(rank == 0 ? GetInput().data() + 2 : nullptr, sendcounts.data(), displs.data(), MPI_INT,
139
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 local_data.data(), extended_rows * width_, MPI_INT, 0, MPI_COMM_WORLD);
140
141
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> local_result(static_cast<size_t>(local_rows) * static_cast<size_t>(width_));
142
143
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ApplyGaussianFilter(local_data, local_result, local_rows, width_, extended_rows, halo_top);
144
145
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> recvcounts(size);
146
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> recvdispls(size);
147
148 int offset = 0;
149
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int i = 0; i < size; i++) {
150 20 recvcounts[i] = rows_count[i] * width_;
151 20 recvdispls[i] = offset;
152 20 offset += recvcounts[i];
153 }
154
155
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
15 MPI_Gatherv(local_result.data(), local_rows * width_, MPI_INT, rank == 0 ? GetOutput().data() : nullptr,
156 recvcounts.data(), recvdispls.data(), MPI_INT, 0, MPI_COMM_WORLD);
157
158 10 return true;
159 }
160
161 10 bool LazarevaAGaussFilterHorizontalMPI::PostProcessingImpl() {
162 10 int rank = 0;
163 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
164
165
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
166
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 return !GetOutput().empty() && (GetOutput().size() == (static_cast<size_t>(height_) * static_cast<size_t>(width_)));
167 }
168
169 return true;
170 }
171
172 } // namespace lazareva_a_gauss_filter_horizontal
173