| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "kamaletdinov_r_bitwise_int/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 <vector> | ||
| 10 | |||
| 11 | #include "kamaletdinov_r_bitwise_int/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace kamaletdinov_r_bitwise_int { | ||
| 14 | |||
| 15 | namespace { | ||
| 16 | |||
| 17 | 23 | void CountingSortByDigitALL(std::vector<int> &arr, int exp) { | |
| 18 | 23 | const int n = static_cast<int>(arr.size()); | |
| 19 | 23 | const int thread_count = omp_get_max_threads(); | |
| 20 | 23 | std::vector<std::array<int, 10>> local_counts(thread_count); | |
| 21 | |||
| 22 | 23 | #pragma omp parallel default(none) shared(arr, exp, local_counts, n) num_threads(thread_count) | |
| 23 | { | ||
| 24 | const int tid = omp_get_thread_num(); | ||
| 25 | auto ¤t = local_counts.at(tid); | ||
| 26 | current.fill(0); | ||
| 27 | |||
| 28 | #pragma omp for schedule(static) | ||
| 29 | for (int i = 0; i < n; i++) { | ||
| 30 | const int digit = (arr.at(i) / exp) % 10; | ||
| 31 | current.at(digit)++; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | 23 | std::array<int, 10> global_count = {}; | |
| 36 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 23 times.
|
69 | for (int ti = 0; ti < thread_count; ti++) { |
| 37 |
2/2✓ Branch 0 taken 460 times.
✓ Branch 1 taken 46 times.
|
506 | for (int di = 0; di < 10; di++) { |
| 38 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
|
460 | global_count.at(di) += local_counts.at(ti).at(di); |
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | 23 | std::array<int, 10> global_start = {}; | |
| 43 |
2/2✓ Branch 0 taken 207 times.
✓ Branch 1 taken 23 times.
|
230 | for (int di = 1; di < 10; di++) { |
| 44 | 207 | global_start.at(di) = global_start.at(di - 1) + global_count.at(di - 1); | |
| 45 | } | ||
| 46 | |||
| 47 |
1/4✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
23 | std::vector<std::array<int, 10>> thread_offsets(thread_count); |
| 48 |
2/2✓ Branch 0 taken 230 times.
✓ Branch 1 taken 23 times.
|
253 | for (int di = 0; di < 10; di++) { |
| 49 | 230 | int offset = global_start.at(di); | |
| 50 |
2/2✓ Branch 0 taken 460 times.
✓ Branch 1 taken 230 times.
|
690 | for (int ti = 0; ti < thread_count; ti++) { |
| 51 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 460 times.
|
460 | thread_offsets.at(ti).at(di) = offset; |
| 52 | 460 | offset += local_counts.at(ti).at(di); | |
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 |
1/4✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
23 | std::vector<int> output(n); |
| 57 | |||
| 58 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | #pragma omp parallel default(none) shared(arr, exp, output, n, thread_count, thread_offsets) num_threads(thread_count) |
| 59 | { | ||
| 60 | const int tid = omp_get_thread_num(); | ||
| 61 | auto positions = thread_offsets.at(tid); | ||
| 62 | |||
| 63 | #pragma omp for schedule(static) | ||
| 64 | for (int i = 0; i < n; i++) { | ||
| 65 | const int digit = (arr.at(i) / exp) % 10; | ||
| 66 | output.at(positions.at(digit)++) = arr.at(i); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | arr.swap(output); | ||
| 71 | 23 | } | |
| 72 | |||
| 73 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 9 times.
|
26 | void RadixSortPositiveALL(std::vector<int> &arr) { |
| 74 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 9 times.
|
26 | if (arr.empty()) { |
| 75 | return; | ||
| 76 | } | ||
| 77 | |||
| 78 | 17 | int max_val = *std::ranges::max_element(arr); | |
| 79 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 4 times.
|
27 | for (int exp = 1; max_val / exp > 0; exp *= 10) { |
| 80 | 23 | CountingSortByDigitALL(arr, exp); | |
| 81 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
|
23 | if (exp > max_val / 10) { |
| 82 | break; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
|
16 | void LocalBitwiseSort(std::vector<int> &arr) { |
| 88 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
|
16 | if (arr.size() <= 1) { |
| 89 | 3 | return; | |
| 90 | } | ||
| 91 | |||
| 92 | 13 | std::vector<int> neg; | |
| 93 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | std::vector<int> pos; |
| 94 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | neg.reserve(arr.size()); |
| 95 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | pos.reserve(arr.size()); |
| 96 | |||
| 97 |
2/2✓ Branch 0 taken 1380 times.
✓ Branch 1 taken 13 times.
|
1393 | for (int val : arr) { |
| 98 |
2/2✓ Branch 0 taken 684 times.
✓ Branch 1 taken 696 times.
|
1380 | if (val < 0) { |
| 99 |
1/4✓ Branch 1 taken 684 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
684 | neg.push_back(-val); |
| 100 | } else { | ||
| 101 | pos.push_back(val); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | RadixSortPositiveALL(neg); |
| 106 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | RadixSortPositiveALL(pos); |
| 107 | |||
| 108 | std::size_t idx = 0; | ||
| 109 |
2/2✓ Branch 0 taken 684 times.
✓ Branch 1 taken 13 times.
|
697 | for (int i = static_cast<int>(neg.size()) - 1; i >= 0; i--) { |
| 110 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 684 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 684 times.
|
684 | arr.at(idx++) = -neg.at(i); |
| 111 | } | ||
| 112 |
2/2✓ Branch 0 taken 696 times.
✓ Branch 1 taken 13 times.
|
709 | for (int v : pos) { |
| 113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 696 times.
|
696 | arr.at(idx++) = v; |
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | 8 | std::vector<int> MergeSorted(const std::vector<int> &a, const std::vector<int> &b) { | |
| 118 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | std::vector<int> result; |
| 119 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | result.reserve(a.size() + b.size()); |
| 120 | std::size_t i = 0; | ||
| 121 | std::size_t j = 0; | ||
| 122 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 698 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 690 times.
|
698 | while (i < a.size() && j < b.size()) { |
| 123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 690 times.
|
690 | if (a[i] <= b[j]) { |
| 124 | ✗ | result.push_back(a[i++]); | |
| 125 | } else { | ||
| 126 |
1/2✓ Branch 0 taken 690 times.
✗ Branch 1 not taken.
|
690 | result.push_back(b[j++]); |
| 127 | } | ||
| 128 | } | ||
| 129 |
2/2✓ Branch 0 taken 693 times.
✓ Branch 1 taken 8 times.
|
701 | while (i < a.size()) { |
| 130 |
1/2✓ Branch 0 taken 693 times.
✗ Branch 1 not taken.
|
693 | result.push_back(a[i++]); |
| 131 | } | ||
| 132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | while (j < b.size()) { |
| 133 | ✗ | result.push_back(b[j++]); | |
| 134 | } | ||
| 135 | 8 | return result; | |
| 136 | } | ||
| 137 | |||
| 138 | } // namespace | ||
| 139 | |||
| 140 | 20 | void BitwiseSortALL(std::vector<int> &arr) { | |
| 141 | 20 | int rank = 0; | |
| 142 | 20 | int size = 1; | |
| 143 | 20 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 144 | 20 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 145 | |||
| 146 | 20 | int total = static_cast<int>(arr.size()); | |
| 147 | 20 | MPI_Bcast(&total, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 148 | |||
| 149 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
|
20 | if (total <= 1) { |
| 150 | 4 | return; | |
| 151 | } | ||
| 152 | |||
| 153 | 16 | std::vector<int> send_counts(size); | |
| 154 |
1/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
16 | std::vector<int> displs(size); |
| 155 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
48 | for (int i = 0; i < size; i++) { |
| 156 |
4/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 16 times.
|
58 | send_counts[i] = (total / size) + (i < total % size ? 1 : 0); |
| 157 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | displs[i] = (i == 0) ? 0 : displs[i - 1] + send_counts[i - 1]; |
| 158 | } | ||
| 159 | |||
| 160 |
1/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
16 | std::vector<int> local_data(send_counts[rank]); |
| 161 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | MPI_Scatterv(arr.data(), send_counts.data(), displs.data(), MPI_INT, local_data.data(), send_counts[rank], MPI_INT, 0, |
| 162 | MPI_COMM_WORLD); | ||
| 163 | |||
| 164 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | LocalBitwiseSort(local_data); |
| 165 | |||
| 166 |
2/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
16 | std::vector<int> recv_counts(size); |
| 167 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | MPI_Gather(&send_counts[rank], 1, MPI_INT, recv_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 168 | |||
| 169 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
16 | if (rank == 0) { |
| 170 |
1/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8 | std::vector<int> all_data(total); |
| 171 |
1/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8 | std::vector<int> recv_displs(size); |
| 172 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
16 | for (int i = 1; i < size; i++) { |
| 173 | 8 | recv_displs[i] = recv_displs[i - 1] + recv_counts[i - 1]; | |
| 174 | } | ||
| 175 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | MPI_Gatherv(local_data.data(), send_counts[rank], MPI_INT, all_data.data(), recv_counts.data(), recv_displs.data(), |
| 176 | MPI_INT, 0, MPI_COMM_WORLD); | ||
| 177 | |||
| 178 |
1/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8 | std::vector<int> merged = {all_data.begin(), all_data.begin() + recv_counts[0]}; |
| 179 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
16 | for (int i = 1; i < size; i++) { |
| 180 |
1/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8 | std::vector<int> chunk(all_data.begin() + recv_displs[i], all_data.begin() + recv_displs[i] + recv_counts[i]); |
| 181 |
2/6✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
16 | merged = MergeSorted(merged, chunk); |
| 182 | } | ||
| 183 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | arr = merged; |
| 184 | } else { | ||
| 185 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | MPI_Gatherv(local_data.data(), send_counts[rank], MPI_INT, nullptr, nullptr, nullptr, MPI_INT, 0, MPI_COMM_WORLD); |
| 186 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | arr.resize(total); |
| 187 | } | ||
| 188 | |||
| 189 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | MPI_Bcast(arr.data(), total, MPI_INT, 0, MPI_COMM_WORLD); |
| 190 | } | ||
| 191 | |||
| 192 | 20 | KamaletdinovRBitwiseIntALL::KamaletdinovRBitwiseIntALL(const InType &in) { | |
| 193 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 194 | 20 | GetInput() = in; | |
| 195 | GetOutput() = 0; | ||
| 196 | 20 | } | |
| 197 | |||
| 198 | 20 | bool KamaletdinovRBitwiseIntALL::ValidationImpl() { | |
| 199 | 20 | return GetInput() >= 0; | |
| 200 | } | ||
| 201 | |||
| 202 | 20 | bool KamaletdinovRBitwiseIntALL::PreProcessingImpl() { | |
| 203 | 20 | int n = GetInput(); | |
| 204 | 20 | data_.resize(n); | |
| 205 |
2/2✓ Branch 0 taken 2768 times.
✓ Branch 1 taken 20 times.
|
2788 | for (int i = 0; i < n; i++) { |
| 206 | 2768 | data_[i] = (n / 2) - i; | |
| 207 | } | ||
| 208 | 20 | return true; | |
| 209 | } | ||
| 210 | |||
| 211 | 20 | bool KamaletdinovRBitwiseIntALL::RunImpl() { | |
| 212 | 20 | BitwiseSortALL(data_); | |
| 213 | 20 | return true; | |
| 214 | } | ||
| 215 | |||
| 216 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
|
20 | bool KamaletdinovRBitwiseIntALL::PostProcessingImpl() { |
| 217 | bool sorted = std::ranges::is_sorted(data_); | ||
| 218 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
20 | GetOutput() = sorted ? GetInput() : 0; |
| 219 | 20 | return true; | |
| 220 | } | ||
| 221 | |||
| 222 | } // namespace kamaletdinov_r_bitwise_int | ||
| 223 |