GCC Code Coverage Report


Directory: ./
File: tasks/shakirova_e_sobel_edge_detection/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 97 99 98.0%
Functions: 10 10 100.0%
Branches: 52 90 57.8%

Line Branch Exec Source
1 #include "shakirova_e_sobel_edge_detection/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <thread>
9 #include <vector>
10
11 #include "shakirova_e_sobel_edge_detection/common/include/common.hpp"
12 #include "util/include/util.hpp"
13
14 namespace shakirova_e_sobel_edge_detection {
15
16 namespace {
17
18 24 void ProcessRowsALL(const int *inp, int *out, int w, int row_begin, int row_end) {
19
2/2
✓ Branch 0 taken 1561 times.
✓ Branch 1 taken 24 times.
1585 for (int row = row_begin; row < row_end; ++row) {
20 1561 const int *prev = inp + static_cast<ptrdiff_t>((row)*w);
21 1561 const int *curr = inp + static_cast<ptrdiff_t>((row + 1) * w);
22 1561 const int *next = inp + static_cast<ptrdiff_t>((row + 2) * w);
23 int *out_row = out + static_cast<ptrdiff_t>(row * w);
24
25
2/2
✓ Branch 0 taken 814589 times.
✓ Branch 1 taken 1561 times.
816150 for (int col = 1; col < w - 1; ++col) {
26 814589 const int gx =
27 814589 -prev[col - 1] + prev[col + 1] - (2 * curr[col - 1]) + (2 * curr[col + 1]) - next[col - 1] + next[col + 1];
28 814589 const int gy = -prev[col - 1] - (2 * prev[col]) - prev[col + 1] + next[col - 1] + (2 * next[col]) + next[col + 1];
29
30 814589 const int agx = std::abs(gx);
31 814589 const int agy = std::abs(gy);
32 814589 const int magnitude = (((std::max(agx, agy) * 123) + (std::min(agx, agy) * 51)) >> 7);
33 814589 out_row[col] = magnitude > 255 ? 255 : magnitude;
34 }
35 }
36 24 }
37
38 12 void ComputeDistribution(int mpi_size, int inner_rows, std::vector<int> &row_counts, std::vector<int> &row_offsets) {
39
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int i = 0; i < mpi_size; ++i) {
40
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
46 row_counts[i] = (inner_rows / mpi_size) + (i < inner_rows % mpi_size ? 1 : 0);
41
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 row_offsets[i] = (i == 0) ? 0 : row_offsets[i - 1] + row_counts[i - 1];
42 }
43 12 }
44
45 12 void ComputeScatterParams(int mpi_size, int w, const std::vector<int> &row_counts, const std::vector<int> &row_offsets,
46 std::vector<int> &send_counts, std::vector<int> &send_displs) {
47
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int i = 0; i < mpi_size; ++i) {
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (row_counts[i] == 0) {
49 send_counts[i] = 0;
50 send_displs[i] = (i == 0) ? 0 : send_displs[i - 1];
51 } else {
52 24 send_counts[i] = (row_counts[i] + 2) * w;
53 24 send_displs[i] = row_offsets[i] * w;
54 }
55 }
56 12 }
57
58 12 void RunThreads(const int *lb, int *lo, int w, int local_inner, int num_stl) {
59 12 std::vector<std::thread> threads;
60
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 threads.reserve(static_cast<size_t>(num_stl));
61
62
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int tid = 0; tid < num_stl; ++tid) {
63
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 threads.emplace_back([lb, lo, w, local_inner, num_stl, tid]() {
64 24 const int chunk = local_inner / num_stl;
65 24 const int row_begin = (tid * chunk);
66
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 const int row_end = (tid == num_stl - 1) ? local_inner : row_begin + chunk;
67 24 ProcessRowsALL(lb, lo, w, row_begin, row_end);
68 24 });
69 }
70
71
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (auto &th : threads) {
72
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 th.join();
73 }
74 12 }
75
76 } // namespace
77
78
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 ShakirovaESobelEdgeDetectionALL::ShakirovaESobelEdgeDetectionALL(const InType &in) {
79 SetTypeOfTask(GetStaticTypeOfTask());
80 GetInput() = in;
81 GetOutput().clear();
82 12 }
83
84 12 bool ShakirovaESobelEdgeDetectionALL::ValidationImpl() {
85 12 int initialized = 0;
86 12 MPI_Initialized(&initialized);
87
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (initialized != 0) {
88 12 int rank = 0;
89 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
90
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
91 return GetInput().IsValid();
92 }
93 return true;
94 }
95 return GetInput().IsValid();
96 }
97
98 12 bool ShakirovaESobelEdgeDetectionALL::PreProcessingImpl() {
99 12 int rank = 0;
100 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
101
102 12 int w = 0;
103 12 int h = 0;
104
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
105 6 w = GetInput().width;
106 6 h = GetInput().height;
107 }
108 12 MPI_Bcast(&w, 1, MPI_INT, 0, MPI_COMM_WORLD);
109 12 MPI_Bcast(&h, 1, MPI_INT, 0, MPI_COMM_WORLD);
110
111 12 GetOutput().assign(static_cast<size_t>(w) * static_cast<size_t>(h), 0);
112 12 return true;
113 }
114
115 12 bool ShakirovaESobelEdgeDetectionALL::RunImpl() {
116 12 int rank = 0;
117 12 int mpi_size = 1;
118 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
119 12 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
120
121 12 int w = 0;
122 12 int h = 0;
123
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
124 6 w = GetInput().width;
125 6 h = GetInput().height;
126 }
127 12 MPI_Bcast(&w, 1, MPI_INT, 0, MPI_COMM_WORLD);
128 12 MPI_Bcast(&h, 1, MPI_INT, 0, MPI_COMM_WORLD);
129
130
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 if (h < 3 || w < 3) {
131 return true;
132 }
133
134 12 const int inner_rows = h - 2;
135 12 const int num_stl = ppc::util::GetNumThreads();
136
137 12 std::vector<int> row_counts(mpi_size);
138
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> row_offsets(mpi_size);
139 12 ComputeDistribution(mpi_size, inner_rows, row_counts, row_offsets);
140
141
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 const int local_inner = row_counts[rank];
142
143
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> send_counts(mpi_size);
144
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> send_displs(mpi_size);
145 12 ComputeScatterParams(mpi_size, w, row_counts, row_offsets, send_counts, send_displs);
146
147
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 const int local_buf_rows = (local_inner > 0) ? (local_inner + 2) : 0;
148
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> local_buf(static_cast<size_t>(local_buf_rows) * static_cast<size_t>(w), 0);
149
150
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 const int *inp_ptr = (rank == 0) ? GetInput().pixels.data() : nullptr;
151
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Scatterv(inp_ptr, send_counts.data(), send_displs.data(), MPI_INT, local_buf.data(), local_buf_rows * w, MPI_INT,
152 0, MPI_COMM_WORLD);
153
154
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> local_out(static_cast<size_t>(local_inner) * static_cast<size_t>(w), 0);
155
156
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (local_inner > 0) {
157
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 RunThreads(local_buf.data(), local_out.data(), w, local_inner, num_stl);
158 }
159
160
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> recv_counts(mpi_size);
161
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> recv_displs(mpi_size);
162
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int i = 0; i < mpi_size; ++i) {
163 24 recv_counts[i] = row_counts[i] * w;
164 24 recv_displs[i] = (row_offsets[i] + 1) * w;
165 }
166
167
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(local_out.data(), local_inner * w, MPI_INT, GetOutput().data(), recv_counts.data(), recv_displs.data(),
168 MPI_INT, 0, MPI_COMM_WORLD);
169
170
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(GetOutput().data(), static_cast<int>(GetOutput().size()), MPI_INT, 0, MPI_COMM_WORLD);
171
172 return true;
173 }
174
175 12 bool ShakirovaESobelEdgeDetectionALL::PostProcessingImpl() {
176 12 return true;
177 }
178
179 } // namespace shakirova_e_sobel_edge_detection
180