GCC Code Coverage Report


Directory: ./
File: tasks/shemetov_d_gauss_filter_linear/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 88 88 100.0%
Functions: 10 10 100.0%
Branches: 52 92 56.5%

Line Branch Exec Source
1 #include "shemetov_d_gauss_filter_linear/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <cstdint>
8 #include <utility>
9 #include <vector>
10
11 #include "shemetov_d_gauss_filter_linear/common/include/common.hpp"
12
13 namespace shemetov_d_gauss_filter_linear {
14
15
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 GaussFilterMPI::GaussFilterMPI(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 GetInput() = in;
18
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 GetOutput() = in;
19 8 }
20
21 260094 Pixel GaussFilterMPI::ApplyKernel(const InType &in, int i, int j, const std::vector<std::vector<float>> &kernel) {
22 260094 float channel_red = 0.F;
23 260094 float channel_green = 0.F;
24 260094 float channel_blue = 0.F;
25
26
2/2
✓ Branch 0 taken 780282 times.
✓ Branch 1 taken 260094 times.
1040376 for (int ki = -1; ki <= 1; ++ki) {
27
2/2
✓ Branch 0 taken 2340846 times.
✓ Branch 1 taken 780282 times.
3121128 for (int kj = -1; kj <= 1; ++kj) {
28 2340846 const auto &lnk_pixel = in[i + ki][j + kj];
29 2340846 float coefficient = kernel[ki + 1][kj + 1];
30
31 2340846 channel_red += coefficient * static_cast<float>(lnk_pixel.channel_red);
32 2340846 channel_green += coefficient * static_cast<float>(lnk_pixel.channel_green);
33 2340846 channel_blue += coefficient * static_cast<float>(lnk_pixel.channel_blue);
34 }
35 }
36
37 260094 Pixel m_pixel = {.channel_red = static_cast<uint8_t>(std::clamp(channel_red, 0.F, 255.F)),
38 260094 .channel_green = static_cast<uint8_t>(std::clamp(channel_green, 0.F, 255.F)),
39 260094 .channel_blue = static_cast<uint8_t>(std::clamp(channel_blue, 0.F, 255.F))};
40 260094 return m_pixel;
41 }
42
43 6 void GaussFilterMPI::ComputeLocalBlock(const InType &in, int start_row, std::vector<std::vector<Pixel>> &local_out) {
44 const std::vector<std::vector<float>> kernel = {
45
4/10
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
24 {1.F / 16, 2.F / 16, 1.F / 16}, {2.F / 16, 4.F / 16, 2.F / 16}, {1.F / 16, 2.F / 16, 1.F / 16}};
46
47
2/2
✓ Branch 0 taken 656 times.
✓ Branch 1 taken 6 times.
662 for (int i = 0; i < local_rows; ++i) {
48 656 const int global_row = start_row + i;
49
50
4/4
✓ Branch 0 taken 653 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 650 times.
656 if (global_row == 0 || global_row == height - 1) {
51 6 continue;
52 }
53
54
2/2
✓ Branch 0 taken 260094 times.
✓ Branch 1 taken 650 times.
260744 for (int j = 1; j < width - 1; ++j) {
55 260094 local_out[static_cast<size_t>(i)][static_cast<size_t>(j)] = ApplyKernel(in, global_row, j, kernel);
56 }
57 }
58
3/10
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
12 }
59
60 1998 std::vector<uint8_t> GaussFilterMPI::SendColumns(const std::vector<std::vector<Pixel>> &local_out, size_t column) {
61 1998 const auto sc_size = static_cast<size_t>(local_rows) * 3;
62 1998 std::vector<uint8_t> send_columns(sc_size);
63
64
1/2
✓ Branch 0 taken 265390 times.
✗ Branch 1 not taken.
265390 for (size_t i = 0; std::cmp_less(i, local_rows); ++i) {
65 263392 send_columns[(i * 3)] = local_out[i][column].channel_red;
66 263392 send_columns[(i * 3) + 1] = local_out[i][column].channel_green;
67 263392 send_columns[(i * 3) + 2] = local_out[i][column].channel_blue;
68 }
69
70 1998 return send_columns;
71 }
72
73 999 void GaussFilterMPI::RecieveColumns(std::vector<uint8_t> &recieve_columns, size_t column,
74 std::vector<std::vector<Pixel>> &out) {
75
1/2
✓ Branch 0 taken 264391 times.
✗ Branch 1 not taken.
264391 for (size_t i = 0; std::cmp_less(i, height); ++i) {
76 263392 out[i][column].channel_red = recieve_columns[(i * 3)];
77 263392 out[i][column].channel_green = recieve_columns[(i * 3) + 1];
78 263392 out[i][column].channel_blue = recieve_columns[(i * 3) + 2];
79 }
80 999 }
81
82 6 void GaussFilterMPI::GatherResult(const std::vector<std::vector<Pixel>> &local_out, const InType &in,
83 std::vector<std::vector<Pixel>> &out) {
84 6 std::vector<int> string_count(size, 0);
85
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int rank_idx = 0; rank_idx < size; ++rank_idx) {
86
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 int distribution = rank_idx < extra_rows ? 1 : 0;
87 12 string_count[rank_idx] = (base_rows + distribution) * 3;
88 }
89
90
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displacement(size, 0);
91
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int rank_idx = 1; rank_idx < size; ++rank_idx) {
92 6 displacement[rank_idx] = displacement[rank_idx - 1] + string_count[rank_idx - 1];
93 }
94
95
1/2
✓ Branch 0 taken 2004 times.
✗ Branch 1 not taken.
2004 for (size_t j = 0; std::cmp_less(j, width); ++j) {
96
1/2
✓ Branch 1 taken 1998 times.
✗ Branch 2 not taken.
1998 auto send_columns = SendColumns(local_out, j);
97
98
2/2
✓ Branch 0 taken 999 times.
✓ Branch 1 taken 999 times.
1998 if (rank == 0) {
99 999 const auto rc_size = static_cast<size_t>(height) * 3;
100
2/6
✓ Branch 1 taken 999 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 999 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
999 std::vector<uint8_t> recieve_columns(rc_size);
101
102
1/2
✓ Branch 1 taken 999 times.
✗ Branch 2 not taken.
999 MPI_Gatherv(send_columns.data(), local_rows * 3, MPI_UNSIGNED_CHAR, recieve_columns.data(), string_count.data(),
103 displacement.data(), MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
104
105 999 RecieveColumns(recieve_columns, j, out);
106 } else {
107
1/2
✓ Branch 1 taken 999 times.
✗ Branch 2 not taken.
999 MPI_Gatherv(send_columns.data(), local_rows * 3, MPI_UNSIGNED_CHAR, nullptr, nullptr, nullptr, MPI_UNSIGNED_CHAR,
108 0, MPI_COMM_WORLD);
109 }
110 }
111
112
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rank == 0) {
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 659 times.
659 for (size_t i = 0; std::cmp_less(i, height); ++i) {
114 656 out[i][0] = in[i][0];
115 656 out[i][width - 1] = in[i][width - 1];
116 }
117 999 for (size_t j = 0; std::cmp_less(j, width); ++j) {
118 999 out[0][j] = in[0][j];
119 999 out[height - 1][j] = in[height - 1][j];
120 }
121 }
122 6 }
123
124
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 bool GaussFilterMPI::ValidationImpl() {
125 const auto &in = GetInput();
126
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 return !in.empty() && !in[0].empty();
127 }
128
129 8 bool GaussFilterMPI::PreProcessingImpl() {
130 8 return true;
131 }
132
133 8 bool GaussFilterMPI::RunImpl() {
134 8 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
135 8 MPI_Comm_size(MPI_COMM_WORLD, &size);
136
137 const auto &in = GetInput();
138 auto &out = GetOutput();
139
140 8 height = static_cast<int>(in.size());
141 8 width = static_cast<int>(in[0].size());
142
143
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
8 if (height < 3 || width < 3) {
144 2 out = in;
145 2 return true;
146 }
147
148 6 base_rows = height / size;
149 6 extra_rows = height % size;
150
151
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 local_rows = base_rows + ((rank < extra_rows) ? 1 : 0);
152 std::vector<std::vector<Pixel>> local_out(static_cast<size_t>(local_rows),
153
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 std::vector<Pixel>(static_cast<size_t>(width)));
154
155
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 const int start_row = (rank * base_rows) + std::min(rank, extra_rows);
156
157
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 ComputeLocalBlock(in, start_row, local_out);
158
159
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 GatherResult(local_out, in, out);
160
161 return true;
162 6 }
163
164 8 bool GaussFilterMPI::PostProcessingImpl() {
165 8 return true;
166 }
167
168 } // namespace shemetov_d_gauss_filter_linear
169