GCC Code Coverage Report


Directory: ./
File: tasks/mityaeva_d_contrast_enhancement_histogram_stretching/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 91 94 96.8%
Functions: 8 8 100.0%
Branches: 68 104 65.4%

Line Branch Exec Source
1 #include "mityaeva_d_contrast_enhancement_histogram_stretching/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <cstdint>
9 #include <utility>
10 #include <vector>
11
12 #include "mityaeva_d_contrast_enhancement_histogram_stretching/common/include/common.hpp"
13
14 namespace mityaeva_d_contrast_enhancement_histogram_stretching {
15
16 namespace {
17
18 18 std::pair<uint8_t, uint8_t> FindGlobalMinMax(const std::vector<uint8_t> &local_pixels) {
19 18 unsigned char local_min = 255;
20 18 unsigned char local_max = 0;
21
22
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 18 times.
66 for (uint8_t p : local_pixels) {
23 auto v = static_cast<unsigned char>(p);
24 48 local_min = std::min(local_min, v);
25 48 local_max = std::max(local_max, v);
26 }
27
28 18 unsigned char global_min = 0;
29 18 unsigned char global_max = 0;
30
31 18 MPI_Allreduce(&local_min, &global_min, 1, MPI_UNSIGNED_CHAR, MPI_MIN, MPI_COMM_WORLD);
32 18 MPI_Allreduce(&local_max, &global_max, 1, MPI_UNSIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
33
34 18 return {static_cast<uint8_t>(global_min), static_cast<uint8_t>(global_max)};
35 }
36
37 18 std::vector<uint8_t> ProcessLocalPixels(const std::vector<uint8_t> &local_pixels, uint8_t global_min,
38 uint8_t global_max) {
39
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (global_min == global_max) {
40 6 return local_pixels;
41 }
42
43 12 const double scale = 255.0 / static_cast<double>(global_max - global_min);
44
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<uint8_t> result;
45
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 result.reserve(local_pixels.size());
46
47
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 12 times.
41 for (uint8_t p : local_pixels) {
48 29 double v = static_cast<double>(p - global_min) * scale;
49 29 int r = static_cast<int>(std::round(v));
50
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 7 times.
51 r = std::max(0, std::min(255, r));
51
1/4
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
29 result.push_back(static_cast<uint8_t>(r));
52 }
53
54 return result;
55 }
56
57 9 void BuildCountsDispls(int total_pixels, int size, std::vector<int> &counts, std::vector<int> &displs) {
58 9 counts.assign(size, 0);
59 9 displs.assign(size, 0);
60
61 9 int base = total_pixels / size;
62 9 int rem = total_pixels % size;
63 int offset = 0;
64
65
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 9 times.
27 for (int i = 0; i < size; ++i) {
66
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
32 counts[i] = base + (i < rem ? 1 : 0);
67 18 displs[i] = offset;
68 18 offset += counts[i];
69 }
70 9 }
71
72 int LocalCount(int total_pixels, int rank, int size) {
73 18 int base = total_pixels / size;
74 18 int rem = total_pixels % size;
75 36 return base + (rank < rem ? 1 : 0);
76 }
77
78 } // namespace
79
80
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 ContrastEnhancementMPI::ContrastEnhancementMPI(const InType &in) {
81 SetTypeOfTask(GetStaticTypeOfTask());
82
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 GetInput() = in;
83 18 GetOutput() = std::vector<uint8_t>{};
84 18 }
85
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 bool ContrastEnhancementMPI::ValidationImpl() {
87 const auto &input = GetInput();
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (input.size() < 3) {
89 return false;
90 }
91
92 18 width_ = static_cast<int>(input[0]);
93 18 height_ = static_cast<int>(input[1]);
94
95
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (width_ <= 0 || height_ <= 0) {
96 return false;
97 }
98
99 18 total_pixels_ = width_ * height_;
100 18 return input.size() == static_cast<size_t>(total_pixels_) + 2;
101 }
102
103 18 bool ContrastEnhancementMPI::PreProcessingImpl() {
104 18 return true;
105 }
106
107 18 bool ContrastEnhancementMPI::RunImpl() {
108 try {
109 18 int rank = 0;
110 18 int size = 0;
111
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
112
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Comm_size(MPI_COMM_WORLD, &size);
113
114
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
115 const auto &input = GetInput();
116 9 width_ = static_cast<int>(input[0]);
117 9 height_ = static_cast<int>(input[1]);
118 9 total_pixels_ = width_ * height_;
119 }
120
121
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(&width_, 1, MPI_INT, 0, MPI_COMM_WORLD);
122
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(&height_, 1, MPI_INT, 0, MPI_COMM_WORLD);
123
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(&total_pixels_, 1, MPI_INT, 0, MPI_COMM_WORLD);
124
125
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 int my_pixels = LocalCount(total_pixels_, rank, size);
126
127 18 std::vector<int> counts;
128 18 std::vector<int> displs;
129
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
130
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 BuildCountsDispls(total_pixels_, size, counts, displs);
131 }
132
133
1/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18 std::vector<uint8_t> local_pixels(static_cast<size_t>(my_pixels));
134
135 const unsigned char *sendbuf = nullptr;
136
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
137 9 sendbuf = reinterpret_cast<const unsigned char *>(GetInput().data() + 2);
138 }
139
140
5/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
36 MPI_Scatterv(sendbuf, (rank == 0 ? counts.data() : nullptr), (rank == 0 ? displs.data() : nullptr),
141 MPI_UNSIGNED_CHAR, reinterpret_cast<unsigned char *>(local_pixels.data()), my_pixels,
142 MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
143
144
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 auto [global_min, global_max] = FindGlobalMinMax(local_pixels);
145
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 std::vector<uint8_t> local_result = ProcessLocalPixels(local_pixels, global_min, global_max);
146
147
1/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18 std::vector<uint8_t> final_output(static_cast<size_t>(total_pixels_) + 2);
148
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
149 9 final_output[0] = static_cast<uint8_t>(width_);
150 9 final_output[1] = static_cast<uint8_t>(height_);
151 }
152
153
5/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
27 MPI_Gatherv(reinterpret_cast<const unsigned char *>(local_result.data()), my_pixels, MPI_UNSIGNED_CHAR,
154 (rank == 0 ? reinterpret_cast<unsigned char *>(final_output.data() + 2) : nullptr),
155
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 (rank == 0 ? counts.data() : nullptr), (rank == 0 ? displs.data() : nullptr), MPI_UNSIGNED_CHAR, 0,
156 MPI_COMM_WORLD);
157
158 18 int final_size = 0;
159
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
160 9 final_size = static_cast<int>(final_output.size());
161 }
162
163
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(&final_size, 1, MPI_INT, 0, MPI_COMM_WORLD);
164
165
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank != 0) {
166
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 final_output.resize(final_size);
167 }
168
169
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(reinterpret_cast<unsigned char *>(final_output.data()), final_size, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
170
171 GetOutput() = std::move(final_output);
172
173
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Barrier(MPI_COMM_WORLD);
174 return true;
175 } catch (...) {
176 return false;
177 }
178 }
179
180
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 bool ContrastEnhancementMPI::PostProcessingImpl() {
181 const auto &output = GetOutput();
182
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (output.size() < 2) {
183 return false;
184 }
185
186 18 int out_w = static_cast<int>(output[0]);
187 18 int out_h = static_cast<int>(output[1]);
188
189
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (out_w != width_ || out_h != height_) {
190 return false;
191 }
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (output.size() != static_cast<size_t>(total_pixels_) + 2) {
193 return false;
194 }
195
196 return true;
197 }
198
199 } // namespace mityaeva_d_contrast_enhancement_histogram_stretching
200