| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "kiselev_i_max_value_in_strings/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstddef> | ||
| 7 | #include <limits> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "kiselev_i_max_value_in_strings/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace kiselev_i_max_value_in_strings { | ||
| 14 | |||
| 15 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | KiselevITestTaskMPI::KiselevITestTaskMPI(const InType &in) { |
| 16 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 17 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto in_copy = in; |
| 18 | 32 | GetInput() = std::move(in_copy); | |
| 19 | GetOutput().clear(); | ||
| 20 | 32 | } | |
| 21 | |||
| 22 | 32 | bool KiselevITestTaskMPI::ValidationImpl() { | |
| 23 | const auto &matrix = GetInput(); | ||
| 24 | if (matrix.empty()) { | ||
| 25 | return true; | ||
| 26 | } | ||
| 27 | return true; | ||
| 28 | } | ||
| 29 | |||
| 30 | 32 | bool KiselevITestTaskMPI::PreProcessingImpl() { | |
| 31 | const auto &matrix = GetInput(); | ||
| 32 | 32 | GetOutput().resize(matrix.size()); | |
| 33 | 32 | return true; | |
| 34 | } | ||
| 35 | |||
| 36 | 32 | void KiselevITestTaskMPI::DistributeRowLengths(const std::vector<std::vector<int>> &matrix, int total_rows, | |
| 37 | int world_rank, int world_size, std::vector<int> &local_row_lengths, | ||
| 38 | std::vector<int> &len_counts, std::vector<int> &len_displs) { | ||
| 39 | 32 | std::vector<int> all_row_lengths; | |
| 40 | 32 | int base = total_rows / world_size; | |
| 41 | 32 | int rem = total_rows % world_size; | |
| 42 | |||
| 43 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 44 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | all_row_lengths.resize(static_cast<size_t>(total_rows)); |
| 45 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 16 times.
|
60 | for (int i = 0; i < total_rows; ++i) { |
| 46 | 44 | all_row_lengths[static_cast<size_t>(i)] = static_cast<int>(matrix[static_cast<size_t>(i)].size()); | |
| 47 | } | ||
| 48 | |||
| 49 | int offset = 0; | ||
| 50 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
48 | for (int pr = 0; pr < world_size; ++pr) { |
| 51 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
|
52 | len_counts[pr] = base + (pr < rem ? 1 : 0); |
| 52 | 32 | len_displs[pr] = offset; | |
| 53 | 32 | offset += len_counts[pr]; | |
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Scatterv(all_row_lengths.data(), len_counts.data(), len_displs.data(), MPI_INT, local_row_lengths.data(), |
| 58 | static_cast<int>(local_row_lengths.size()), MPI_INT, 0, MPI_COMM_WORLD); | ||
| 59 | 32 | } | |
| 60 | |||
| 61 | 32 | void KiselevITestTaskMPI::DistributeValues(const std::vector<std::vector<int>> &matrix, int world_rank, int world_size, | |
| 62 | const std::vector<int> &len_counts, const std::vector<int> &len_displs, | ||
| 63 | std::vector<int> &local_values) { | ||
| 64 | 32 | std::vector<int> val_counts(world_size); | |
| 65 |
1/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32 | std::vector<int> val_displs(world_size); |
| 66 | |||
| 67 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 68 | int offset = 0; | ||
| 69 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
48 | for (int pr = 0; pr < world_size; ++pr) { |
| 70 | int count = 0; | ||
| 71 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 32 times.
|
76 | for (int i = 0; i < len_counts[pr]; ++i) { |
| 72 | 44 | count += static_cast<int>(matrix[len_displs[pr] + i].size()); | |
| 73 | } | ||
| 74 | 32 | val_counts[pr] = count; | |
| 75 | 32 | val_displs[pr] = offset; | |
| 76 | 32 | offset += count; | |
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Bcast(val_counts.data(), world_size, MPI_INT, 0, MPI_COMM_WORLD); |
| 81 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Bcast(val_displs.data(), world_size, MPI_INT, 0, MPI_COMM_WORLD); |
| 82 | |||
| 83 | 32 | std::vector<int> flat_matrix; | |
| 84 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 85 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | int total_elements = val_displs[world_size - 1] + val_counts[world_size - 1]; |
| 86 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | flat_matrix.reserve(static_cast<size_t>(total_elements)); |
| 87 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 16 times.
|
60 | for (const auto &row : matrix) { |
| 88 | 44 | flat_matrix.insert(flat_matrix.end(), row.begin(), row.end()); | |
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
|
32 | int my_count = val_counts[world_rank]; |
| 93 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
|
32 | if (my_count > 0) { |
| 94 |
1/2✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
|
23 | local_values.resize(my_count); |
| 95 | } else { | ||
| 96 | local_values.clear(); | ||
| 97 | } | ||
| 98 | |||
| 99 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Scatterv(flat_matrix.data(), val_counts.data(), val_displs.data(), MPI_INT, local_values.data(), my_count, |
| 100 | MPI_INT, 0, MPI_COMM_WORLD); | ||
| 101 | 32 | } | |
| 102 | |||
| 103 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
|
32 | void KiselevITestTaskMPI::ComputeLocalMax(const std::vector<int> &local_values, |
| 104 | const std::vector<int> &local_row_lengths, std::vector<int> &local_result) { | ||
| 105 | size_t n_rows = local_row_lengths.size(); | ||
| 106 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
|
32 | if (n_rows == 0) { |
| 107 | return; | ||
| 108 | } | ||
| 109 | |||
| 110 | 25 | local_result.resize(n_rows); | |
| 111 | int pos = 0; | ||
| 112 | |||
| 113 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 25 times.
|
69 | for (size_t rw = 0; rw < n_rows; ++rw) { |
| 114 | 44 | int len = local_row_lengths[rw]; | |
| 115 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 40 times.
|
44 | if (len == 0) { |
| 116 | // пустая строка → используем минимальное значение int | ||
| 117 | 4 | local_result[rw] = std::numeric_limits<int>::min(); | |
| 118 | } else { | ||
| 119 | 40 | int tmp_max = local_values[pos]; | |
| 120 |
2/2✓ Branch 0 taken 149 times.
✓ Branch 1 taken 40 times.
|
189 | for (int j = 1; j < len; ++j) { |
| 121 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 89 times.
|
209 | tmp_max = std::max(tmp_max, local_values[pos + j]); |
| 122 | } | ||
| 123 | 40 | local_result[rw] = tmp_max; | |
| 124 | } | ||
| 125 | 44 | pos += len; | |
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | 32 | bool KiselevITestTaskMPI::RunImpl() { | |
| 130 | const auto &matrix = GetInput(); | ||
| 131 | auto &result_vector = GetOutput(); | ||
| 132 | |||
| 133 | 32 | int world_rank = 0; | |
| 134 | 32 | int world_size = 0; | |
| 135 | 32 | MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); | |
| 136 | 32 | MPI_Comm_size(MPI_COMM_WORLD, &world_size); | |
| 137 | |||
| 138 | 32 | int total_rows = static_cast<int>(matrix.size()); | |
| 139 | 32 | MPI_Bcast(&total_rows, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 140 | |||
| 141 | 32 | int base = total_rows / world_size; | |
| 142 | 32 | int rem = total_rows % world_size; | |
| 143 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
|
32 | int local_row_count = base + (world_rank < rem ? 1 : 0); |
| 144 | |||
| 145 | 32 | std::vector<int> local_row_lengths(local_row_count); | |
| 146 |
1/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32 | std::vector<int> len_counts(world_size); |
| 147 |
1/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32 | std::vector<int> len_displs(world_size); |
| 148 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | DistributeRowLengths(matrix, total_rows, world_rank, world_size, local_row_lengths, len_counts, len_displs); |
| 149 | |||
| 150 | 32 | std::vector<int> local_values; | |
| 151 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | DistributeValues(matrix, world_rank, world_size, len_counts, len_displs, local_values); |
| 152 | |||
| 153 | 32 | std::vector<int> local_result; | |
| 154 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | ComputeLocalMax(local_values, local_row_lengths, local_result); |
| 155 | |||
| 156 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | if (world_rank == 0) { |
| 157 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | result_vector.resize(total_rows); |
| 158 | } | ||
| 159 | |||
| 160 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | MPI_Gatherv(local_result.data(), local_row_count, MPI_INT, result_vector.data(), len_counts.data(), len_displs.data(), |
| 161 | MPI_INT, 0, MPI_COMM_WORLD); | ||
| 162 | |||
| 163 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 4 times.
|
32 | if (total_rows > 0) { |
| 164 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | MPI_Bcast(result_vector.data(), total_rows, MPI_INT, 0, MPI_COMM_WORLD); |
| 165 | } | ||
| 166 | |||
| 167 | 32 | return true; | |
| 168 | } | ||
| 169 | |||
| 170 | 32 | bool KiselevITestTaskMPI::PostProcessingImpl() { | |
| 171 | 32 | return true; | |
| 172 | } | ||
| 173 | |||
| 174 | } // namespace kiselev_i_max_value_in_strings | ||
| 175 |