GCC Code Coverage Report


Directory: ./
File: tasks/morozov_n_sobels_filter/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 89 92 96.7%
Functions: 9 10 90.0%
Branches: 45 60 75.0%

Line Branch Exec Source
1 #include "morozov_n_sobels_filter/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cmath>
8 #include <cstddef>
9 #include <cstdint>
10 #include <vector>
11
12 #include "morozov_n_sobels_filter/common/include/common.hpp"
13 #include "util/include/util.hpp"
14
15 namespace morozov_n_sobels_filter {
16
17
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MorozovNSobelsFilterALL::MorozovNSobelsFilterALL(const InType &in) {
18 SetTypeOfTask(GetStaticTypeOfTask());
19 GetInput() = in;
20
21 10 result_image_.height = in.height;
22 10 result_image_.width = in.width;
23
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 result_image_.pixels.resize(result_image_.height * result_image_.width, 0);
24
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
25
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Comm_size(MPI_COMM_WORLD, &size_);
26 10 }
27
28 10 bool MorozovNSobelsFilterALL::ValidationImpl() {
29 const Image &input = GetInput();
30
3/6
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 return (input.height == result_image_.height) && (input.width == result_image_.width) &&
31 10 (input.pixels.size() == result_image_.pixels.size());
32 }
33
34 void MorozovNSobelsFilterALL::SplitRows(size_t global_rows, size_t proc_num, size_t &start, size_t &count) const {
35 25 size_t base = global_rows / size_;
36 25 size_t rem = global_rows % size_;
37
38 count = base + (proc_num < rem ? 1 : 0);
39
40
3/4
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
25 start = (proc_num * base) + std::min<size_t>(proc_num, rem);
41 }
42
43 5 void MorozovNSobelsFilterALL::SendImageDataFromZeroProc(const Image &global, size_t halo) {
44
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int proc = 0; proc < size_; proc++) {
45 size_t proc_start{};
46 size_t proc_rows{};
47
48
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 SplitRows(global.height, proc, proc_start, proc_rows);
49
50
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 size_t top = (proc_start == 0) ? 0 : halo;
51
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 size_t bottom = (proc_start + proc_rows == global.height) ? 0 : halo;
52 10 size_t offset = proc_start - top;
53
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 size_t total = proc_rows + top + bottom;
54
55 10 const auto *ptr = global.pixels.data() + (offset * global.width);
56
57
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (proc == 0) {
58 5 std::copy(ptr, ptr + (total * global.width), local_image_.pixels.begin());
59 } else {
60 5 MPI_Send(ptr, static_cast<int>(total * global.width), MPI_UNSIGNED_CHAR, proc, 0, MPI_COMM_WORLD);
61 }
62 }
63 5 }
64
65 10 void MorozovNSobelsFilterALL::CollectResult() {
66 const int halo = 1;
67
68
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 size_t top = (start_row_ == 0) ? 0 : halo;
69
70 10 auto *send_ptr = result_image_.pixels.data() + (top * result_image_.width);
71
72 10 size_t send_count = local_rows_ * result_image_.width;
73
74
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank_ == 0) {
75 5 Image global;
76
77 5 global.width = result_image_.width;
78 5 global.height = GetInput().height;
79
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 global.pixels.resize(global.width * global.height);
80
81 5 std::copy(send_ptr, send_ptr + send_count, global.pixels.begin());
82
83
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for (int proc = 1; proc < size_; proc++) {
84 size_t start{};
85 size_t rows{};
86
87
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 SplitRows(global.height, proc, start, rows);
88
89
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 MPI_Recv(global.pixels.data() + (start * global.width), static_cast<int>(rows * global.width), MPI_UNSIGNED_CHAR,
90 proc, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
91 }
92
93 GetOutput() = global;
94
95 } else {
96 5 MPI_Send(send_ptr, static_cast<int>(send_count), MPI_UNSIGNED_CHAR, 0, 1, MPI_COMM_WORLD);
97 }
98 10 }
99
100
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 bool MorozovNSobelsFilterALL::PreProcessingImpl() {
101 const int halo = 1;
102
103 const Image &global = GetInput();
104
105 10 size_t width{};
106 10 size_t height{};
107
108
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank_ == 0) {
109 5 width = global.width;
110 5 height = global.height;
111 }
112
113 10 MPI_Bcast(&width, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
114 10 MPI_Bcast(&height, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
115
116
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 SplitRows(height, rank_, start_row_, local_rows_);
117
118 10 size_t top_halo = (start_row_ == 0) ? 0 : halo;
119
120 10 size_t bottom_halo = (start_row_ + local_rows_ == height) ? 0 : halo;
121
122 10 size_t send_rows = local_rows_ + top_halo + bottom_halo;
123
124 10 local_image_.width = width;
125 10 local_image_.height = send_rows;
126 10 local_image_.pixels.resize(send_rows * width);
127
128
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank_ == 0) {
129 5 SendImageDataFromZeroProc(global, static_cast<size_t>(halo));
130 } else {
131 5 MPI_Recv(local_image_.pixels.data(), static_cast<int>(send_rows * width), MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD,
132 MPI_STATUS_IGNORE);
133 }
134
135 10 return true;
136 }
137
138 10 bool MorozovNSobelsFilterALL::RunImpl() {
139 10 result_image_.width = local_image_.width;
140 10 result_image_.height = local_image_.height;
141 10 result_image_.pixels.resize(local_image_.pixels.size());
142
143 constexpr size_t kBegin = 1;
144 10 size_t end = local_image_.height - 1;
145
146 10 Filter(local_image_, result_image_, kBegin, end);
147 10 CollectResult();
148
149 10 return true;
150 }
151
152 10 void MorozovNSobelsFilterALL::Filter(const Image &img, Image &local_result, size_t start_row, size_t end_row) {
153 10 #pragma omp parallel for schedule(static) default(none) shared(img, local_result, start_row, end_row) \
154 10 num_threads(ppc::util::GetNumThreads())
155 for (size_t id_y = start_row; id_y < end_row; id_y++) {
156 for (size_t id_x = 1; id_x < img.width - 1; id_x++) {
157 size_t pixel_id = (id_y * img.width) + id_x;
158 local_result.pixels[pixel_id] = CalculateNewPixelColor(img, id_x, id_y);
159 }
160 }
161 10 }
162
163 133 uint8_t MorozovNSobelsFilterALL::CalculateNewPixelColor(const Image &img, size_t x, size_t y) {
164 constexpr int kRadX = 1;
165 constexpr int kRadY = 1;
166 133 constexpr size_t kZero = 0;
167
168 int grad_x = 0;
169 int grad_y = 0;
170
171
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 133 times.
532 for (int row_offset = -kRadY; row_offset <= kRadY; row_offset++) {
172
2/2
✓ Branch 0 taken 1197 times.
✓ Branch 1 taken 399 times.
1596 for (int col_offset = -kRadX; col_offset <= kRadX; col_offset++) {
173 1197 size_t id_x = std::clamp(x + col_offset, kZero, img.width - 1);
174 1197 size_t id_y = std::clamp(y + row_offset, kZero, img.height - 1);
175 1197 size_t pixel_id = (id_y * img.width) + id_x;
176
177 1197 grad_x += img.pixels[pixel_id] * kKernelX.at(row_offset + kRadY).at(col_offset + kRadX);
178 1197 grad_y += img.pixels[pixel_id] * kKernelY.at(row_offset + kRadY).at(col_offset + kRadX);
179 }
180 }
181
182 133 int gradient = static_cast<int>(std::sqrt((grad_x * grad_x) + (grad_y * grad_y)));
183 gradient = std::clamp(gradient, 0, 255);
184
185 133 return static_cast<uint8_t>(gradient);
186 }
187
188 10 bool MorozovNSobelsFilterALL::PostProcessingImpl() {
189 Image &out = GetOutput();
190
191
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank_ != 0) {
192 5 out.width = result_image_.width;
193
194 5 out.height = GetInput().height;
195
196 5 out.pixels.resize(out.width * out.height);
197 }
198
199 10 MPI_Bcast(out.pixels.data(), static_cast<int>(out.pixels.size()), MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
200
201 10 return true;
202 }
203
204 } // namespace morozov_n_sobels_filter
205