GCC Code Coverage Report


Directory: ./
File: tasks/kiselev_i_linear_histogram_stretch/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 50 50 100.0%
Functions: 5 5 100.0%
Branches: 28 46 60.9%

Line Branch Exec Source
1 #include "kiselev_i_linear_histogram_stretch/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <limits>
9 #include <vector>
10
11 #include "kiselev_i_linear_histogram_stretch/common/include/common.hpp"
12
13 namespace kiselev_i_linear_histogram_stretch {
14
15
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 KiselevITestTaskMPI::KiselevITestTaskMPI(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18
19
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!in.pixels.empty()) {
20
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 GetOutput().resize(in.pixels.size());
21 }
22 26 }
23
24 26 bool KiselevITestTaskMPI::ValidationImpl() {
25 const auto &img = GetInput();
26
3/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
26 return img.width > 0 && img.height > 0 && img.pixels.size() == img.width * img.height;
27 }
28
29 26 bool KiselevITestTaskMPI::PreProcessingImpl() {
30 26 return true;
31 }
32
33 26 bool KiselevITestTaskMPI::RunImpl() {
34 26 int rank = 0;
35 26 int size = 1;
36 26 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
37 26 MPI_Comm_size(MPI_COMM_WORLD, &size);
38
39 constexpr int kRoot = 0;
40
41 26 std::size_t total_size = 0;
42
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == kRoot) {
43 13 total_size = GetInput().pixels.size();
44 }
45
46 26 MPI_Bcast(&total_size, 1, MPI_UNSIGNED_LONG_LONG, kRoot, MPI_COMM_WORLD);
47
48 26 const std::size_t base = total_size / static_cast<std::size_t>(size);
49 26 const std::size_t extra = total_size % static_cast<std::size_t>(size);
50
51 26 std::vector<int> counts(size, 0);
52
1/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
26 std::vector<int> offsets(size, 0);
53
54
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == kRoot) {
55 std::size_t shift = 0;
56 13 const auto size_sz = static_cast<std::size_t>(size);
57
58
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13 times.
39 for (std::size_t index = 0; index < size_sz; ++index) {
59
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
26 const std::size_t add = (index < extra) ? 1 : 0;
60 26 counts[static_cast<int>(index)] = static_cast<int>(base + add);
61 26 offsets[static_cast<int>(index)] = static_cast<int>(shift);
62 26 shift += static_cast<std::size_t>(counts[static_cast<int>(index)]);
63 }
64 }
65
66
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 int local_count = 0;
67
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Scatter(counts.data(), 1, MPI_INT, &local_count, 1, MPI_INT, kRoot, MPI_COMM_WORLD);
68
69
1/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
26 std::vector<unsigned char> local_pixels(static_cast<std::size_t>(local_count));
70
71
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Scatterv(GetInput().pixels.data(), counts.data(), offsets.data(), MPI_UNSIGNED_CHAR, local_pixels.data(),
72 local_count, MPI_UNSIGNED_CHAR, kRoot, MPI_COMM_WORLD);
73
74 26 unsigned char local_min = std::numeric_limits<unsigned char>::max();
75 26 unsigned char local_max = std::numeric_limits<unsigned char>::min();
76
77
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 26 times.
74 for (unsigned char px : local_pixels) {
78 48 local_min = std::min(local_min, px);
79 48 local_max = std::max(local_max, px);
80 }
81
82 26 unsigned char global_min = 0;
83 26 unsigned char global_max = 0;
84
85
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Allreduce(&local_min, &global_min, 1, MPI_UNSIGNED_CHAR, MPI_MIN, MPI_COMM_WORLD);
86
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Allreduce(&local_max, &global_max, 1, MPI_UNSIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
87
88
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 if (global_min != global_max) {
89 24 const double scale = 255.0 / static_cast<double>(global_max - global_min);
90
91
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 24 times.
66 for (unsigned char &px : local_pixels) {
92 42 const double value = static_cast<double>(px - global_min) * scale;
93 42 px = static_cast<unsigned char>(std::lround(value));
94 }
95 }
96
97
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Gatherv(local_pixels.data(), local_count, MPI_UNSIGNED_CHAR, GetOutput().data(), counts.data(), offsets.data(),
98 MPI_UNSIGNED_CHAR, kRoot, MPI_COMM_WORLD);
99
100 26 return true;
101 }
102
103 26 bool KiselevITestTaskMPI::PostProcessingImpl() {
104 26 return true;
105 }
106
107 } // namespace kiselev_i_linear_histogram_stretch
108