| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "buzulukski_d_gaus_gorizontal/all/include/ops_all.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | #include <omp.h> | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <cstdint> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "buzulukski_d_gaus_gorizontal/common/include/common.hpp" | ||
| 13 | |||
| 14 | namespace buzulukski_d_gaus_gorizontal { | ||
| 15 | |||
| 16 | namespace { | ||
| 17 | constexpr int kChannels = 3; | ||
| 18 | constexpr int kKernelSum = 16; | ||
| 19 | constexpr std::array<std::array<int, 3>, 3> kKernel = {{{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}}; | ||
| 20 | |||
| 21 | ✗ | uint8_t CalculatePixelALL(const uint8_t *in, int py, int px, int w, int h, int ch) { | |
| 22 | int sum = 0; | ||
| 23 | ✗ | for (int ky = -1; ky <= 1; ++ky) { | |
| 24 | ✗ | for (int kx = -1; kx <= 1; ++kx) { | |
| 25 | ✗ | int ny = std::clamp(py + ky, 0, h - 1); | |
| 26 | ✗ | int nx = std::clamp(px + kx, 0, w - 1); | |
| 27 | ✗ | size_t idx = ((static_cast<size_t>(ny) * w + nx) * kChannels) + ch; | |
| 28 | ✗ | sum += static_cast<int>(in[idx]) * kKernel.at(static_cast<size_t>(ky) + 1).at(static_cast<size_t>(kx) + 1); | |
| 29 | } | ||
| 30 | } | ||
| 31 | ✗ | return static_cast<uint8_t>(sum / kKernelSum); | |
| 32 | } | ||
| 33 | } // namespace | ||
| 34 | |||
| 35 | ✗ | BuzulukskiDGausGorizontalALL::BuzulukskiDGausGorizontalALL(const InType &in) : BaseTask() { | |
| 36 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 37 | ✗ | GetInput() = in; | |
| 38 | GetOutput() = 0; | ||
| 39 | ✗ | } | |
| 40 | |||
| 41 | ✗ | bool BuzulukskiDGausGorizontalALL::ValidationImpl() { | |
| 42 | ✗ | return GetInput() >= 3; | |
| 43 | } | ||
| 44 | |||
| 45 | ✗ | bool BuzulukskiDGausGorizontalALL::PreProcessingImpl() { | |
| 46 | ✗ | width_ = GetInput(); | |
| 47 | ✗ | height_ = GetInput(); | |
| 48 | ✗ | size_t total_size = static_cast<size_t>(width_) * height_ * kChannels; | |
| 49 | ✗ | input_image_.assign(total_size, 100); | |
| 50 | ✗ | output_image_.assign(total_size, 0); | |
| 51 | ✗ | return true; | |
| 52 | } | ||
| 53 | |||
| 54 | ✗ | bool BuzulukskiDGausGorizontalALL::RunImpl() { | |
| 55 | ✗ | int rank = 0; | |
| 56 | ✗ | int size = 0; | |
| 57 | ✗ | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 58 | ✗ | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 59 | |||
| 60 | ✗ | int h = height_; | |
| 61 | ✗ | int w = width_; | |
| 62 | |||
| 63 | ✗ | int rows_per_proc = h / size; | |
| 64 | ✗ | int start_row = rank * rows_per_proc; | |
| 65 | ✗ | int end_row = (rank == size - 1) ? h : (rank + 1) * rows_per_proc; | |
| 66 | |||
| 67 | const uint8_t *input_ptr = input_image_.data(); | ||
| 68 | ✗ | std::vector<uint8_t> local_output((static_cast<size_t>(end_row) - start_row) * w * kChannels); | |
| 69 | uint8_t *local_ptr = local_output.data(); | ||
| 70 | |||
| 71 | ✗ | #pragma omp parallel for collapse(2) default(none) shared(start_row, end_row, w, h, input_ptr, local_ptr) | |
| 72 | for (int py = start_row; py < end_row; ++py) { | ||
| 73 | for (int px = 0; px < w; ++px) { | ||
| 74 | for (int ch = 0; ch < kChannels; ++ch) { | ||
| 75 | int local_py = py - start_row; | ||
| 76 | size_t local_idx = ((static_cast<size_t>(local_py) * w + px) * kChannels) + ch; | ||
| 77 | local_ptr[local_idx] = CalculatePixelALL(input_ptr, py, px, w, h, ch); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | ✗ | std::vector<int> recv_counts; | |
| 83 | ✗ | std::vector<int> displs; | |
| 84 | |||
| 85 | ✗ | if (rank == 0) { | |
| 86 | ✗ | recv_counts.resize(size); | |
| 87 | ✗ | displs.resize(size); | |
| 88 | ✗ | for (int i = 0; i < size; ++i) { | |
| 89 | ✗ | int s = i * rows_per_proc; | |
| 90 | ✗ | int e = (i == size - 1) ? h : (i + 1) * rows_per_proc; | |
| 91 | ✗ | recv_counts[i] = (e - s) * w * kChannels; | |
| 92 | ✗ | displs[i] = s * w * kChannels; | |
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | ✗ | MPI_Gatherv(local_ptr, static_cast<int>(local_output.size()), MPI_UNSIGNED_CHAR, output_image_.data(), | |
| 97 | recv_counts.data(), displs.data(), MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD); | ||
| 98 | |||
| 99 | ✗ | return true; | |
| 100 | } | ||
| 101 | |||
| 102 | ✗ | bool BuzulukskiDGausGorizontalALL::PostProcessingImpl() { | |
| 103 | ✗ | int rank = 0; | |
| 104 | ✗ | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 105 | ✗ | if (rank == 0) { | |
| 106 | int64_t total_sum = 0; | ||
| 107 | ✗ | for (const auto &val : output_image_) { | |
| 108 | ✗ | total_sum += static_cast<int64_t>(val); | |
| 109 | } | ||
| 110 | ✗ | GetOutput() = static_cast<int>(total_sum / static_cast<int64_t>(output_image_.size())); | |
| 111 | } | ||
| 112 | ✗ | return true; | |
| 113 | } | ||
| 114 | |||
| 115 | } // namespace buzulukski_d_gaus_gorizontal | ||
| 116 |