| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "romanova_v_jacobi_method/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <tuple> | ||
| 9 | #include <utility> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "romanova_v_jacobi_method/common/include/common.hpp" | ||
| 13 | |||
| 14 | namespace romanova_v_jacobi_method { | ||
| 15 | |||
| 16 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | RomanovaVJacobiMethodMPI::RomanovaVJacobiMethodMPI(const InType &in) { |
| 17 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 18 | GetInput() = in; | ||
| 19 | GetOutput(); | ||
| 20 | 22 | } | |
| 21 | |||
| 22 | 22 | bool RomanovaVJacobiMethodMPI::ValidationImpl() { | |
| 23 | 22 | bool status = true; | |
| 24 | |||
| 25 | 22 | int rank = 0; | |
| 26 | 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 27 | |||
| 28 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 29 | 11 | std::vector<OutType> a = std::get<1>(GetInput()); | |
| 30 | |||
| 31 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | OutType x = std::get<0>(GetInput()); |
| 32 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | OutType b = std::get<2>(GetInput()); |
| 33 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
11 | status = status && !a.empty(); |
| 34 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 11 times.
|
57 | for (size_t i = 0; i < a.size(); i++) { |
| 35 |
2/4✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
|
46 | status = status && (a.size() == a[i].size()); |
| 36 | } | ||
| 37 | |||
| 38 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | status = status && IsDiagonallyDominant(a); |
| 39 | |||
| 40 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
11 | status = status && (a.size() == x.size()); |
| 41 |
3/6✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
11 | status = status && (a.size() == b.size()); |
| 42 | 11 | } | |
| 43 | |||
| 44 | 22 | MPI_Bcast(&status, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); | |
| 45 | 22 | return status; | |
| 46 | } | ||
| 47 | |||
| 48 | 22 | bool RomanovaVJacobiMethodMPI::PreProcessingImpl() { | |
| 49 | 22 | int rank = 0; | |
| 50 | 22 | int n = 0; | |
| 51 | |||
| 52 | 22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 53 | 22 | MPI_Comm_size(MPI_COMM_WORLD, &n); | |
| 54 | |||
| 55 | 22 | std::vector<int> send_counts_a(n); | |
| 56 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | vector_counts_ = std::vector<int>(n); |
| 57 | |||
| 58 |
1/4✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | std::vector<int> displs_scatt_a(n); |
| 59 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | vector_displs_ = std::vector<int>(n); |
| 60 | |||
| 61 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 62 | 11 | n_ = std::get<1>(GetInput()).size(); | |
| 63 | } | ||
| 64 | |||
| 65 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(&n_, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 66 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | x_ = OutType(n_); |
| 67 | |||
| 68 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 69 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | std::vector<OutType> temp_a; |
| 70 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | std::tie(x_, temp_a, b_, eps_, maxIterations_) = GetInput(); |
| 71 | |||
| 72 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 11 times.
|
57 | for (const auto &vec : temp_a) { |
| 73 |
1/2✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
|
46 | A_.insert(A_.end(), vec.begin(), vec.end()); |
| 74 | } | ||
| 75 | 11 | } | |
| 76 | |||
| 77 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(&eps_, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 78 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(&maxIterations_, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 79 | |||
| 80 | 22 | size_t delta = n_ / n; | |
| 81 | 22 | size_t extra = n_ % n; | |
| 82 | |||
| 83 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | local_n_ = delta + (std::cmp_less(rank, extra) ? 1 : 0); |
| 84 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | st_row_ = (rank * delta) + (std::cmp_less(rank, extra) ? rank : extra); |
| 85 | |||
| 86 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | if (rank == 0) { |
| 87 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | send_counts_a = std::vector<int>(n, static_cast<int>(delta * n_)); |
| 88 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | vector_counts_ = std::vector<int>(n, static_cast<int>(delta)); |
| 89 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 11 times.
|
17 | for (size_t i = 0; i < extra; i++) { |
| 90 | 6 | send_counts_a[i] += static_cast<int>(n_); | |
| 91 | 6 | vector_counts_[i]++; | |
| 92 | } | ||
| 93 | |||
| 94 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | for (int i = 1; i < n; i++) { |
| 95 | 11 | displs_scatt_a[i] = displs_scatt_a[i - 1] + send_counts_a[i - 1]; | |
| 96 | 11 | vector_displs_[i] = vector_displs_[i - 1] + vector_counts_[i - 1]; | |
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(vector_counts_.data(), n, MPI_INT, 0, MPI_COMM_WORLD); |
| 101 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(vector_displs_.data(), n, MPI_INT, 0, MPI_COMM_WORLD); |
| 102 | |||
| 103 |
1/4✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | OutType local_data = OutType(local_n_ * n_); |
| 104 |
1/4✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | OutType local_b = OutType(local_n_); |
| 105 | |||
| 106 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | MPI_Bcast(x_.data(), static_cast<int>(n_), MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 107 | |||
| 108 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
|
33 | MPI_Scatterv(rank == 0 ? A_.data() : nullptr, send_counts_a.data(), displs_scatt_a.data(), MPI_DOUBLE, |
| 109 | local_data.data(), static_cast<int>(local_data.size()), MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
| 110 | |||
| 111 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
|
33 | MPI_Scatterv(rank == 0 ? b_.data() : nullptr, vector_counts_.data(), vector_displs_.data(), MPI_DOUBLE, |
| 112 | local_b.data(), static_cast<int>(local_b.size()), MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
| 113 | |||
| 114 | 22 | A_ = std::move(local_data); | |
| 115 | 22 | b_ = std::move(local_b); | |
| 116 | |||
| 117 | 22 | return true; | |
| 118 | } | ||
| 119 | |||
| 120 | 22 | bool RomanovaVJacobiMethodMPI::RunImpl() { | |
| 121 | size_t k = 0; | ||
| 122 | 22 | OutType prev(x_.size(), 0.0); | |
| 123 |
1/4✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | OutType local_x(local_n_); |
| 124 | 22 | double diff = 0.0; | |
| 125 | 22 | double glob_diff = eps_; | |
| 126 |
4/4✓ Branch 0 taken 732 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 730 times.
✓ Branch 3 taken 2 times.
|
752 | while (glob_diff >= eps_ && k < maxIterations_) { |
| 127 | 730 | diff = 0.0; | |
| 128 |
1/2✓ Branch 1 taken 730 times.
✗ Branch 2 not taken.
|
730 | prev = x_; |
| 129 |
2/2✓ Branch 0 taken 1422 times.
✓ Branch 1 taken 730 times.
|
2152 | for (size_t i = 0; i < local_n_; i++) { |
| 130 | double sum = 0.0; | ||
| 131 |
2/2✓ Branch 0 taken 6786 times.
✓ Branch 1 taken 1422 times.
|
8208 | for (size_t j = 0; j < n_; j++) { |
| 132 |
2/2✓ Branch 0 taken 5364 times.
✓ Branch 1 taken 1422 times.
|
6786 | sum += ((st_row_ + i) != j ? A_[(i * n_) + j] * prev[j] : 0); |
| 133 | } | ||
| 134 | 1422 | local_x[i] = (b_[i] - sum) / A_[(i * (n_ + 1)) + st_row_]; | |
| 135 | |||
| 136 | 1422 | diff = std::max(diff, abs(local_x[i] - prev[st_row_ + i])); | |
| 137 | } | ||
| 138 | |||
| 139 |
1/2✓ Branch 1 taken 730 times.
✗ Branch 2 not taken.
|
730 | MPI_Allgatherv(local_x.data(), static_cast<int>(local_n_), MPI_DOUBLE, x_.data(), vector_counts_.data(), |
| 140 | vector_displs_.data(), MPI_DOUBLE, MPI_COMM_WORLD); | ||
| 141 | |||
| 142 |
1/2✓ Branch 1 taken 730 times.
✗ Branch 2 not taken.
|
730 | MPI_Allreduce(&diff, &glob_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); |
| 143 | 730 | k++; | |
| 144 | } | ||
| 145 | 22 | return true; | |
| 146 | } | ||
| 147 | |||
| 148 | 22 | bool RomanovaVJacobiMethodMPI::PostProcessingImpl() { | |
| 149 | 22 | GetOutput() = x_; | |
| 150 | 22 | return true; | |
| 151 | } | ||
| 152 | |||
| 153 | 11 | bool RomanovaVJacobiMethodMPI::IsDiagonallyDominant(const std::vector<OutType> &matrix) { | |
| 154 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 11 times.
|
57 | for (size_t i = 0; i < matrix.size(); i++) { |
| 155 | double sum = 0.0; | ||
| 156 |
2/2✓ Branch 0 taken 246 times.
✓ Branch 1 taken 46 times.
|
292 | for (size_t j = 0; j < matrix[i].size(); j++) { |
| 157 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 46 times.
|
246 | if (i != j) { |
| 158 | 200 | sum += matrix[i][j]; | |
| 159 | } | ||
| 160 | } | ||
| 161 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | if (matrix[i][i] <= sum) { |
| 162 | return false; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | return true; | ||
| 166 | } | ||
| 167 | |||
| 168 | } // namespace romanova_v_jacobi_method | ||
| 169 |