GCC Code Coverage Report


Directory: ./
File: tasks/lopatin_a_sobel_operator/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 42 42 100.0%
Functions: 6 6 100.0%
Branches: 15 28 53.6%

Line Branch Exec Source
1 #include "lopatin_a_sobel_operator/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <algorithm>
7 #include <array>
8 #include <cmath>
9 #include <cstddef>
10 #include <cstdint>
11 #include <utility>
12 #include <vector>
13
14 #include "lopatin_a_sobel_operator/common/include/common.hpp"
15 #include "util/include/util.hpp"
16
17 namespace lopatin_a_sobel_operator {
18
19 const std::array<std::array<int, 3>, 3> kSobelX = {std::array<int, 3>{-1, 0, 1}, std::array<int, 3>{-2, 0, 2},
20 std::array<int, 3>{-1, 0, 1}};
21
22 const std::array<std::array<int, 3>, 3> kSobelY = {std::array<int, 3>{-1, -2, -1}, std::array<int, 3>{0, 0, 0},
23 std::array<int, 3>{1, 2, 1}};
24
25 7 void LopatinASobelOperatorALL::RunSobel(const Image &img, std::size_t start, std::size_t end,
26 lopatin_a_sobel_operator::OutType &output, std::size_t shift) {
27 7 const auto &input_data = img.pixels;
28
29 7 int proc_num = 0;
30 7 MPI_Comm_size(MPI_COMM_WORLD, &proc_num);
31
32 7 #pragma omp parallel for num_threads(ppc::util::GetNumThreads() / proc_num) schedule(static) default(none) \
33 shared(kSobelX, kSobelY, img, input_data, output, start, end, shift)
34 for (std::size_t j = start; j < end; ++j) { // processing only pixels with a full 3 x 3 neighborhood size
35 std::size_t out_row = j - shift;
36 for (std::size_t i = 1; i < img.width - 1; ++i) {
37 int gx = 0;
38 int gy = 0;
39
40 for (int ky = -1; ky <= 1; ++ky) {
41 for (int kx = -1; kx <= 1; ++kx) {
42 std::uint8_t pixel = input_data[((j + ky) * img.width) + (i + kx)];
43 gx += pixel * kSobelX.at(ky + 1).at(kx + 1);
44 gy += pixel * kSobelY.at(ky + 1).at(kx + 1);
45 }
46 }
47
48 auto magnitude = static_cast<int>(round(std::sqrt((gx * gx) + (gy * gy))));
49 output[(out_row * img.width) + i] = (magnitude > img.threshold) ? magnitude : 0;
50 }
51 }
52 7 }
53
54
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 LopatinASobelOperatorALL::LopatinASobelOperatorALL(const InType &in) : h_(in.height), w_(in.width) {
55 SetTypeOfTask(GetStaticTypeOfTask());
56 GetInput() = in;
57 GetOutput().clear();
58 6 }
59
60 6 bool LopatinASobelOperatorALL::ValidationImpl() {
61 const auto &input = GetInput();
62 6 return h_ * w_ == input.pixels.size();
63 }
64
65 6 bool LopatinASobelOperatorALL::PreProcessingImpl() {
66 6 GetOutput().resize(h_ * w_);
67 6 return true;
68 }
69
70 6 bool LopatinASobelOperatorALL::RunImpl() {
71 6 int proc_num = 0;
72 6 MPI_Comm_size(MPI_COMM_WORLD, &proc_num);
73 6 int proc_rank = 0;
74 6 MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
75
76 const auto &input = GetInput();
77
78 6 const auto rows = input.height - 2;
79 6 const auto n_procs = std::min(static_cast<std::size_t>(proc_num), rows);
80
81 6 const std::size_t portion = rows / n_procs;
82
83 6 lopatin_a_sobel_operator::OutType local_output(portion * input.width, 0);
84
85
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (std::cmp_less(proc_rank, n_procs)) {
86 5 std::size_t start = 1 + (proc_rank * portion);
87 5 std::size_t end = 1 + ((proc_rank + 1) * portion);
88
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 RunSobel(input, start, end, local_output, start);
89 }
90
91 auto &output = GetOutput();
92
93
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> recvcounts(proc_num, 0);
94
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displs(proc_num, 0);
95
96
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 for (size_t i = 0; i < n_procs; ++i) {
97 10 recvcounts[i] = static_cast<int>(portion * input.width);
98 10 displs[i] = static_cast<int>((1 + i * portion) * input.width);
99 }
100
101
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
11 int sendcount = std::cmp_less(proc_rank, n_procs) ? static_cast<int>(local_output.size()) : 0;
102
103
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Gatherv(local_output.data(), sendcount, MPI_INT, output.data(), recvcounts.data(), displs.data(), MPI_INT, 0,
104 MPI_COMM_WORLD);
105
106
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (proc_rank == 0) {
107 3 const std::size_t tail = rows % n_procs;
108
109
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (tail != 0) {
110 2 std::size_t start = input.height - 1 - tail;
111
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 RunSobel(input, start, input.height - 1, output, 0);
112 }
113 }
114
115
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Bcast(output.data(), static_cast<int>(output.size()), MPI_INT, 0, MPI_COMM_WORLD);
116
117 6 return true;
118 }
119
120 6 bool LopatinASobelOperatorALL::PostProcessingImpl() {
121 6 return true;
122 }
123
124 } // namespace lopatin_a_sobel_operator
125