GCC Code Coverage Report


Directory: ./
File: tasks/mityaeva_radix/all/src/ops_all.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 65 68 95.6%
Functions: 9 9 100.0%
Branches: 39 64 60.9%

Line Branch Exec Source
1 #include "mityaeva_radix/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <cstddef>
6 #include <cstring>
7 #include <utility>
8 #include <vector>
9
10 #include "mityaeva_radix/common/include/common.hpp"
11 #include "mityaeva_radix/omp/include/sorter_omp.hpp"
12
13 namespace mityaeva_radix {
14
15 namespace {
16
17 24 void ComputeChunkParams(size_t total_size, int mpi_size, std::vector<size_t> &chunk_sizes,
18 std::vector<size_t> &offsets) {
19 24 size_t base_chunk = total_size / mpi_size;
20 24 size_t remainder = total_size % mpi_size;
21
22
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 for (int i = 0; i < mpi_size; ++i) {
23
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 chunk_sizes[i] = base_chunk + (std::cmp_less(i, remainder) ? 1 : 0);
24
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 offsets[i] = (i == 0) ? 0 : offsets[i - 1] + chunk_sizes[i - 1];
25 }
26 24 }
27
28 24 void ScatterData(const std::vector<double> &array, std::vector<double> &local_data,
29 const std::vector<size_t> &chunk_sizes, const std::vector<size_t> &offsets) {
30 24 int mpi_size = static_cast<int>(chunk_sizes.size());
31 24 std::vector<int> send_counts(mpi_size);
32
1/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
24 std::vector<int> send_displs(mpi_size);
33
34
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 for (int i = 0; i < mpi_size; ++i) {
35 48 send_counts[i] = static_cast<int>(chunk_sizes[i]);
36 48 send_displs[i] = static_cast<int>(offsets[i]);
37 }
38
39
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 MPI_Scatterv(array.data(), send_counts.data(), send_displs.data(), MPI_DOUBLE, local_data.data(),
40 static_cast<int>(local_data.size()), MPI_DOUBLE, 0, MPI_COMM_WORLD);
41 24 }
42
43 24 std::vector<double> MergeTwoSorted(const std::vector<double> &left, const std::vector<double> &right) {
44 24 std::vector<double> result(left.size() + right.size());
45 size_t i = 0;
46 size_t j = 0;
47 size_t k = 0;
48
49
4/4
✓ Branch 0 taken 1074 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1062 times.
1086 while (i < left.size() && j < right.size()) {
50
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 531 times.
1062 if (left[i] <= right[j]) {
51 531 result[k++] = left[i++];
52 } else {
53 531 result[k++] = right[j++];
54 }
55 }
56
57
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 24 times.
51 while (i < left.size()) {
58 27 result[k++] = left[i++];
59 }
60
61
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 24 times.
51 while (j < right.size()) {
62 27 result[k++] = right[j++];
63 }
64
65 24 return result;
66 }
67
68 24 void ExchangeAndMerge(int partner, std::vector<double> &merged_data) {
69 24 size_t my_size = merged_data.size();
70 24 size_t partner_size = 0;
71
72 24 MPI_Sendrecv(&my_size, 1, MPI_UNSIGNED_LONG, partner, 0, &partner_size, 1, MPI_UNSIGNED_LONG, partner, 0,
73 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
74
75 24 std::vector<double> partner_data(partner_size);
76
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 MPI_Sendrecv(merged_data.data(), static_cast<int>(my_size), MPI_DOUBLE, partner, 1, partner_data.data(),
77 static_cast<int>(partner_size), MPI_DOUBLE, partner, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
78
79
3/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
48 merged_data = MergeTwoSorted(merged_data, partner_data);
80 24 }
81
82 void ParallelHypercubeMerge(std::vector<double> &merged_data, int mpi_rank, int mpi_size) {
83 int step = 1;
84
85
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 while (step < mpi_size) {
86 24 int partner = mpi_rank ^ step;
87
88
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (partner < mpi_size) {
89
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 ExchangeAndMerge(partner, merged_data);
90 }
91
92 24 step <<= 1;
93 }
94 }
95
96 } // namespace
97
98
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 MityaevaRadixAll::MityaevaRadixAll(const InType &in) {
99 SetTypeOfTask(GetStaticTypeOfTask());
100
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 GetInput() = in;
101 GetOutput() = {};
102 24 }
103
104 24 bool MityaevaRadixAll::ValidationImpl() {
105 24 return !GetInput().empty();
106 }
107
108 24 bool MityaevaRadixAll::PreProcessingImpl() {
109 24 return true;
110 }
111
112 24 bool MityaevaRadixAll::RunImpl() {
113 24 int mpi_rank = 0;
114 24 int mpi_size = 1;
115
116 24 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
117 24 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
118
119 auto &array = GetInput();
120 size_t total_size = array.size();
121
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (total_size == 0) {
123 GetOutput() = array;
124 return true;
125 }
126
127 24 std::vector<size_t> chunk_sizes(mpi_size);
128
1/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
24 std::vector<size_t> offsets(mpi_size);
129 24 ComputeChunkParams(total_size, mpi_size, chunk_sizes, offsets);
130
131
1/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
24 std::vector<double> local_data(chunk_sizes[mpi_rank]);
132
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 ScatterData(array, local_data, chunk_sizes, offsets);
133
134
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 SorterOmp::Sort(local_data);
135
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (mpi_size == 1) {
137 GetOutput() = local_data;
138 return true;
139 }
140
141 std::vector<double> merged_data = std::move(local_data);
142 24 ParallelHypercubeMerge(merged_data, mpi_rank, mpi_size);
143
144
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (mpi_rank == 0) {
145
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GetOutput() = merged_data;
146 } else {
147 GetOutput() = {};
148 }
149
150 return true;
151 }
152
153 24 bool MityaevaRadixAll::PostProcessingImpl() {
154 24 return true;
155 }
156
157 } // namespace mityaeva_radix
158