| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "polukhin_v_string_diff/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <cmath> | ||
| 5 | #include <cstddef> | ||
| 6 | #include <cstdint> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "mpi.h" | ||
| 11 | #include "polukhin_v_string_diff/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace polukhin_v_string_diff { | ||
| 14 | |||
| 15 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | StringDiffTaskMPI::StringDiffTaskMPI(const InType &in) { |
| 16 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 17 | GetInput() = in; | ||
| 18 | 22 | GetOutput() = 0; | |
| 19 | 22 | } | |
| 20 | |||
| 21 | 22 | bool StringDiffTaskMPI::ValidationImpl() { | |
| 22 | 22 | return true; | |
| 23 | } | ||
| 24 | 22 | bool StringDiffTaskMPI::PreProcessingImpl() { | |
| 25 | 22 | return true; | |
| 26 | } | ||
| 27 | 22 | bool StringDiffTaskMPI::PostProcessingImpl() { | |
| 28 | 22 | return true; | |
| 29 | } | ||
| 30 | |||
| 31 | namespace { | ||
| 32 | |||
| 33 | 22 | void BroadcastStringLengths(int rank, int &len1, int &len2) { | |
| 34 | if (rank == 0) { | ||
| 35 | } | ||
| 36 | 22 | MPI_Bcast(&len1, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 37 | 22 | MPI_Bcast(&len2, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 38 | 22 | } | |
| 39 | |||
| 40 | 18 | void PrepareDataDistribution(int rank, int size, int min_len, std::vector<int> &sendcounts, std::vector<int> &displs) { | |
| 41 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | if (rank != 0) { |
| 42 | return; | ||
| 43 | } | ||
| 44 | |||
| 45 | std::ranges::fill(sendcounts, 0); | ||
| 46 | std::ranges::fill(displs, 0); | ||
| 47 | |||
| 48 | 9 | const int els_per_process = (min_len + size - 1) / size; | |
| 49 | int offset = 0; | ||
| 50 | |||
| 51 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 9 times.
|
27 | for (int i = 0; i < size; ++i) { |
| 52 | 18 | const int start = i * els_per_process; | |
| 53 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | const int end = std::min(start + els_per_process, min_len); |
| 54 | |||
| 55 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (start < min_len) { |
| 56 | 18 | sendcounts[i] = end - start; | |
| 57 | } | ||
| 58 | |||
| 59 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | displs[i] = offset; |
| 60 | |||
| 61 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (start < min_len) { |
| 62 | 18 | offset += sendcounts[i]; | |
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | uint64_t ComputeLocalDifferences(const std::vector<char> &local_str1, const std::vector<char> &local_str2) { | ||
| 68 | uint64_t local_count = 0; | ||
| 69 | const size_t recvcount = local_str1.size(); | ||
| 70 | |||
| 71 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 18 times.
|
62 | for (size_t i = 0; i < recvcount; ++i) { |
| 72 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 22 times.
|
44 | if (local_str1[i] != local_str2[i]) { |
| 73 | 22 | ++local_count; | |
| 74 | } | ||
| 75 | } | ||
| 76 | return local_count; | ||
| 77 | } | ||
| 78 | |||
| 79 | 18 | void DistributeStrings(int rank, int recvcount, const std::vector<int> &sendcounts, const std::vector<int> &displs, | |
| 80 | const std::string &str1, const std::string &str2, std::vector<char> &local_str1, | ||
| 81 | std::vector<char> &local_str2) { | ||
| 82 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (recvcount <= 0) { |
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
27 | MPI_Scatterv(rank == 0 ? str1.data() : nullptr, sendcounts.data(), displs.data(), MPI_CHAR, local_str1.data(), |
| 87 | recvcount, MPI_CHAR, 0, MPI_COMM_WORLD); | ||
| 88 | |||
| 89 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
27 | MPI_Scatterv(rank == 0 ? str2.data() : nullptr, sendcounts.data(), displs.data(), MPI_CHAR, local_str2.data(), |
| 90 | recvcount, MPI_CHAR, 0, MPI_COMM_WORLD); | ||
| 91 | } | ||
| 92 | |||
| 93 | 22 | void CollectAndSetResults(int rank, uint64_t local_count, int length_diff, size_t &output) { | |
| 94 | 22 | uint64_t total_count = 0; | |
| 95 | 22 | MPI_Reduce(&local_count, &total_count, 1, MPI_UINT64_T, MPI_SUM, 0, MPI_COMM_WORLD); | |
| 96 | |||
| 97 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 98 | 11 | total_count += static_cast<uint64_t>(length_diff); | |
| 99 | 11 | output = static_cast<size_t>(total_count); | |
| 100 | } | ||
| 101 | |||
| 102 | 11 | uint64_t result = 0; | |
| 103 | if (rank == 0) { | ||
| 104 | 11 | result = total_count; | |
| 105 | } | ||
| 106 | 22 | MPI_Bcast(&result, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD); | |
| 107 | |||
| 108 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank != 0) { |
| 109 | 11 | output = static_cast<size_t>(result); | |
| 110 | } | ||
| 111 | 22 | } | |
| 112 | |||
| 113 | } // namespace | ||
| 114 | |||
| 115 | 22 | bool StringDiffTaskMPI::RunImpl() { | |
| 116 | 22 | int rank = 0; | |
| 117 | 22 | int size = 0; | |
| 118 | 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 119 | 22 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 120 | |||
| 121 | std::string str1; | ||
| 122 | std::string str2; | ||
| 123 | 22 | int len1 = 0; | |
| 124 | 22 | int len2 = 0; | |
| 125 | |||
| 126 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 127 | const auto &input = GetInput(); | ||
| 128 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | str1 = input.first; |
| 129 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | str2 = input.second; |
| 130 | 11 | len1 = static_cast<int>(str1.size()); | |
| 131 | 11 | len2 = static_cast<int>(str2.size()); | |
| 132 | } | ||
| 133 | |||
| 134 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | BroadcastStringLengths(rank, len1, len2); |
| 135 | |||
| 136 | const int min_len = std::min(len1, len2); | ||
| 137 | 22 | const int length_diff = std::abs(len1 - len2); | |
| 138 | |||
| 139 | uint64_t local_count = 0; | ||
| 140 | |||
| 141 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
|
22 | if (min_len > 0) { |
| 142 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | std::vector<int> sendcounts(size, 0); |
| 143 |
1/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18 | std::vector<int> displs(size, 0); |
| 144 | |||
| 145 | 18 | PrepareDataDistribution(rank, size, min_len, sendcounts, displs); | |
| 146 | |||
| 147 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | int recvcount = 0; |
| 148 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recvcount, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 149 | |||
| 150 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (recvcount > 0) { |
| 151 |
1/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18 | std::vector<char> local_str1(recvcount); |
| 152 |
1/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18 | std::vector<char> local_str2(recvcount); |
| 153 | |||
| 154 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | DistributeStrings(rank, recvcount, sendcounts, displs, str1, str2, local_str1, local_str2); |
| 155 | |||
| 156 | local_count = ComputeLocalDifferences(local_str1, local_str2); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | CollectAndSetResults(rank, local_count, length_diff, GetOutput()); |
| 161 | |||
| 162 | 22 | return true; | |
| 163 | } | ||
| 164 | |||
| 165 | } // namespace polukhin_v_string_diff | ||
| 166 |