| 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 |