GCC Code Coverage Report


Directory: ./
File: tasks/vdovin_a_gauss_block/all/src/ops_all.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 52 53 98.1%
Functions: 6 6 100.0%
Branches: 27 42 64.3%

Line Branch Exec Source
1 #include "vdovin_a_gauss_block/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstdint>
8 #include <vector>
9
10 #include "vdovin_a_gauss_block/common/include/common.hpp"
11
12 namespace vdovin_a_gauss_block {
13
14 namespace {
15 constexpr int kChannels = 3;
16 constexpr int kKernelSize = 3;
17 constexpr int kKernelSum = 16;
18 constexpr std::array<std::array<int, kKernelSize>, kKernelSize> kKernel = {{{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}};
19 } // namespace
20
21 20 VdovinAGaussBlockALL::VdovinAGaussBlockALL(const InType &in) {
22 SetTypeOfTask(GetStaticTypeOfTask());
23 20 GetInput() = in;
24 GetOutput() = 0;
25 20 }
26
27 20 bool VdovinAGaussBlockALL::ValidationImpl() {
28 20 return GetInput() >= 3;
29 }
30
31 20 bool VdovinAGaussBlockALL::PreProcessingImpl() {
32 20 width_ = GetInput();
33 20 height_ = GetInput();
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (width_ < 3 || height_ < 3) {
35 input_image_.clear();
36 output_image_.clear();
37 return false;
38 }
39 20 int total = width_ * height_ * kChannels;
40 20 input_image_.assign(total, 100);
41 20 output_image_.assign(total, 0);
42 20 return true;
43 }
44
45 39597 uint8_t VdovinAGaussBlockALL::ComputePixelChannel(const std::vector<uint8_t> &img, int width, int height, int py,
46 int px, int ch) {
47 int sum = 0;
48
2/2
✓ Branch 0 taken 118791 times.
✓ Branch 1 taken 39597 times.
158388 for (int ky = -1; ky <= 1; ky++) {
49
2/2
✓ Branch 0 taken 356373 times.
✓ Branch 1 taken 118791 times.
475164 for (int kx = -1; kx <= 1; kx++) {
50 356373 int ny = std::clamp(py + ky, 0, height - 1);
51 356373 int nx = std::clamp(px + kx, 0, width - 1);
52 356373 sum += img[(((ny * width) + nx) * kChannels) + ch] * kKernel.at(ky + 1).at(kx + 1);
53 }
54 }
55
1/2
✓ Branch 0 taken 39597 times.
✗ Branch 1 not taken.
39597 return static_cast<uint8_t>(std::clamp(sum / kKernelSum, 0, 255));
56 }
57
58
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 bool VdovinAGaussBlockALL::RunImpl() {
59
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (input_image_.empty() || output_image_.empty()) {
60 return false;
61 }
62
63 20 int rank = 0;
64 20 int size = 1;
65 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
66 20 MPI_Comm_size(MPI_COMM_WORLD, &size);
67
68 20 MPI_Bcast(&width_, 1, MPI_INT, 0, MPI_COMM_WORLD);
69 20 MPI_Bcast(&height_, 1, MPI_INT, 0, MPI_COMM_WORLD);
70
71 20 int total_pixels = width_ * height_;
72 20 MPI_Bcast(input_image_.data(), total_pixels * kChannels, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
73
74 20 int rows_per_proc = height_ / size;
75 20 int extra = height_ % size;
76
77 20 std::vector<int> send_counts(size);
78
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> displs(size);
79 int offset = 0;
80
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int pi = 0; pi < size; pi++) {
81
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 int rows = rows_per_proc + (pi < extra ? 1 : 0);
82 40 send_counts[pi] = rows * width_ * kChannels;
83 40 displs[pi] = offset;
84 40 offset += send_counts[pi];
85 }
86
87
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 3 times.
20 int local_rows = rows_per_proc + (rank < extra ? 1 : 0);
88 20 int local_size = local_rows * width_ * kChannels;
89
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<uint8_t> local_output(local_size, 0);
90
91 int row_start = 0;
92
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 20 times.
30 for (int pi = 0; pi < rank; pi++) {
93
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
17 row_start += rows_per_proc + (pi < extra ? 1 : 0);
94 }
95
96
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 #pragma omp parallel for schedule(static) default(none) shared(local_output, local_rows, row_start)
97 for (int ry = 0; ry < local_rows; ry++) {
98 int py = row_start + ry;
99 for (int px = 0; px < width_; px++) {
100 for (int ch = 0; ch < kChannels; ch++) {
101 local_output[(((ry * width_) + px) * kChannels) + ch] =
102 ComputePixelChannel(input_image_, width_, height_, py, px, ch);
103 }
104 }
105 }
106
107
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Allgatherv(local_output.data(), local_size, MPI_UNSIGNED_CHAR, output_image_.data(), send_counts.data(),
108 displs.data(), MPI_UNSIGNED_CHAR, MPI_COMM_WORLD);
109
110 return true;
111 }
112
113
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 bool VdovinAGaussBlockALL::PostProcessingImpl() {
114
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (output_image_.empty()) {
115 return false;
116 }
117 auto total = static_cast<int64_t>(output_image_.size());
118 if (total == 0) {
119 return false;
120 }
121 int64_t sum = 0;
122
2/2
✓ Branch 0 taken 79194 times.
✓ Branch 1 taken 20 times.
79214 for (int64_t idx = 0; idx < total; idx++) {
123 79194 sum += output_image_[idx];
124 }
125 20 GetOutput() = static_cast<int>(sum / total);
126 20 return true;
127 }
128
129 } // namespace vdovin_a_gauss_block
130