| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "zaharov_g_seidel_int_met/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "zaharov_g_seidel_int_met/common/include/common.hpp" | ||
| 11 | |||
| 12 | namespace zaharov_g_seidel_int_met { | ||
| 13 | |||
| 14 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | ZaharovGSeidelIntMetMPI::ZaharovGSeidelIntMetMPI(const InType &in) { |
| 15 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 16 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | GetInput() = in; |
| 17 | 12 | GetOutput() = OutType(); | |
| 18 | 12 | } | |
| 19 | |||
| 20 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | bool ZaharovGSeidelIntMetMPI::ValidationImpl() { |
| 21 | const InType &input = GetInput(); | ||
| 22 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (input.size() < 3) { |
| 23 | return false; | ||
| 24 | } | ||
| 25 | |||
| 26 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
12 | if (input[0] <= 0 || input[1] <= 0.0 || input[2] <= 0) { |
| 27 | return false; | ||
| 28 | } | ||
| 29 | |||
| 30 | 12 | const int system_size = static_cast<int>(input[0]); | |
| 31 | 12 | const int max_iterations = static_cast<int>(input[2]); | |
| 32 | |||
| 33 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | return (static_cast<double>(system_size) == input[0]) && (static_cast<double>(max_iterations) == input[2]); |
| 34 | } | ||
| 35 | |||
| 36 | 12 | bool ZaharovGSeidelIntMetMPI::PreProcessingImpl() { | |
| 37 | try { | ||
| 38 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | MPI_Comm_rank(MPI_COMM_WORLD, &rank_); |
| 39 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | MPI_Comm_size(MPI_COMM_WORLD, &size_); |
| 40 | |||
| 41 | 12 | system_size_ = static_cast<int>(GetInput()[0]); | |
| 42 | 12 | epsilon_ = GetInput()[1]; | |
| 43 | 12 | max_iterations_ = static_cast<int>(GetInput()[2]); | |
| 44 | |||
| 45 | 12 | rows_per_process_ = system_size_ / size_; | |
| 46 | 12 | remainder_ = system_size_ % size_; | |
| 47 | |||
| 48 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | start_row_ = (rank_ * rows_per_process_) + std::min(rank_, remainder_); |
| 49 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | end_row_ = start_row_ + rows_per_process_ + (rank_ < remainder_ ? 1 : 0); |
| 50 | 12 | local_rows_ = end_row_ - start_row_; | |
| 51 | |||
| 52 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | local_A_.resize(local_rows_); |
| 53 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | local_b_.resize(local_rows_); |
| 54 | |||
| 55 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 12 times.
|
232 | for (int local_i = 0; local_i < local_rows_; ++local_i) { |
| 56 | 220 | const int global_i = start_row_ + local_i; | |
| 57 |
1/2✓ Branch 1 taken 220 times.
✗ Branch 2 not taken.
|
220 | local_A_[local_i].resize(system_size_); |
| 58 | |||
| 59 |
2/2✓ Branch 0 taken 14000 times.
✓ Branch 1 taken 220 times.
|
14220 | for (int j = 0; j < system_size_; ++j) { |
| 60 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 13780 times.
|
14000 | if (global_i == j) { |
| 61 | 220 | local_A_[local_i][j] = system_size_ + 1.0; | |
| 62 | } else { | ||
| 63 | 13780 | local_A_[local_i][j] = 1.0 / (static_cast<double>(std::abs(global_i - j)) + 1.0); | |
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | 220 | local_b_[local_i] = static_cast<double>(global_i + 1); | |
| 68 | } | ||
| 69 | |||
| 70 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | x_.resize(system_size_, 0.0); |
| 71 | |||
| 72 | 12 | return true; | |
| 73 | ✗ | } catch (...) { | |
| 74 | return false; | ||
| 75 | ✗ | } | |
| 76 | } | ||
| 77 | |||
| 78 | 12 | bool ZaharovGSeidelIntMetMPI::RunImpl() { | |
| 79 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (system_size_ == 0) { |
| 80 | return false; | ||
| 81 | } | ||
| 82 | |||
| 83 | 12 | std::vector<double> prev_x(system_size_, 0.0); | |
| 84 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | std::vector<double> local_x_new(local_rows_, 0.0); |
| 85 | |||
| 86 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | std::vector<int> recvcounts(size_); |
| 87 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | std::vector<int> displs(size_); |
| 88 | |||
| 89 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
|
36 | for (int i = 0; i < size_; ++i) { |
| 90 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | const int i_start = (i * rows_per_process_) + std::min(i, remainder_); |
| 91 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | const int i_end = i_start + rows_per_process_ + (i < remainder_ ? 1 : 0); |
| 92 | 24 | recvcounts[i] = i_end - i_start; | |
| 93 | 24 | displs[i] = i_start; | |
| 94 | } | ||
| 95 | |||
| 96 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | for (int iter = 0; iter < max_iterations_; ++iter) { |
| 97 | std::ranges::copy(x_, prev_x.begin()); | ||
| 98 | |||
| 99 |
2/2✓ Branch 0 taken 1540 times.
✓ Branch 1 taken 100 times.
|
1640 | for (int local_i = 0; local_i < local_rows_; ++local_i) { |
| 100 | 1540 | const int global_i = start_row_ + local_i; | |
| 101 | 1540 | double sum = local_b_[local_i]; | |
| 102 | const auto &row = local_A_[local_i]; | ||
| 103 | |||
| 104 |
2/2✓ Branch 0 taken 43930 times.
✓ Branch 1 taken 1540 times.
|
45470 | for (int j = 0; j < global_i; ++j) { |
| 105 | 43930 | sum -= row[j] * x_[j]; | |
| 106 | } | ||
| 107 | |||
| 108 |
2/2✓ Branch 0 taken 43930 times.
✓ Branch 1 taken 1540 times.
|
45470 | for (int j = global_i + 1; j < system_size_; ++j) { |
| 109 | 43930 | sum -= row[j] * prev_x[j]; | |
| 110 | } | ||
| 111 | |||
| 112 | 1540 | local_x_new[local_i] = sum / row[global_i]; | |
| 113 | } | ||
| 114 | |||
| 115 |
1/2✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
|
100 | MPI_Allgatherv(local_x_new.data(), local_rows_, MPI_DOUBLE, x_.data(), recvcounts.data(), displs.data(), MPI_DOUBLE, |
| 116 | MPI_COMM_WORLD); | ||
| 117 | |||
| 118 | 100 | double local_max_diff = 0.0; | |
| 119 |
2/2✓ Branch 0 taken 1540 times.
✓ Branch 1 taken 100 times.
|
1640 | for (int local_i = 0; local_i < local_rows_; ++local_i) { |
| 120 | 1540 | const int global_i = start_row_ + local_i; | |
| 121 | 1540 | const double diff = std::abs(x_[global_i] - prev_x[global_i]); | |
| 122 | 1540 | local_max_diff = std::max(diff, local_max_diff); | |
| 123 | } | ||
| 124 | |||
| 125 | 100 | double global_max_diff = 0.0; | |
| 126 |
1/2✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
|
100 | MPI_Allreduce(&local_max_diff, &global_max_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); |
| 127 | |||
| 128 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 12 times.
|
100 | if (global_max_diff < epsilon_) { |
| 129 | break; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 |
2/6✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
24 | GetOutput() = std::vector<double>(x_.begin(), x_.end()); |
| 134 | |||
| 135 | return true; | ||
| 136 | } | ||
| 137 | |||
| 138 | 12 | bool ZaharovGSeidelIntMetMPI::PostProcessingImpl() { | |
| 139 | try { | ||
| 140 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (rank_ != 0) { |
| 141 | return true; | ||
| 142 | } | ||
| 143 | |||
| 144 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (x_.size() != static_cast<std::size_t>(system_size_)) { |
| 145 | return false; | ||
| 146 | } | ||
| 147 | |||
| 148 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | std::vector<std::vector<double>> matrix_a(system_size_, std::vector<double>(system_size_)); |
| 149 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<double> vector_b(system_size_); |
| 150 | |||
| 151 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 6 times.
|
226 | for (int i = 0; i < system_size_; ++i) { |
| 152 | 220 | vector_b[i] = static_cast<double>(i + 1); | |
| 153 |
2/2✓ Branch 0 taken 14000 times.
✓ Branch 1 taken 220 times.
|
14220 | for (int j = 0; j < system_size_; ++j) { |
| 154 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 13780 times.
|
14000 | if (i == j) { |
| 155 | 220 | matrix_a[i][j] = system_size_ + 1.0; | |
| 156 | } else { | ||
| 157 | 13780 | matrix_a[i][j] = 1.0 / (static_cast<double>(std::abs(i - j)) + 1.0); | |
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | double residual_norm = 0.0; | ||
| 163 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 6 times.
|
226 | for (int i = 0; i < system_size_; ++i) { |
| 164 | double sum = 0.0; | ||
| 165 |
2/2✓ Branch 0 taken 14000 times.
✓ Branch 1 taken 220 times.
|
14220 | for (int j = 0; j < system_size_; ++j) { |
| 166 | 14000 | sum += matrix_a[i][j] * x_[j]; | |
| 167 | } | ||
| 168 | 220 | residual_norm += std::abs(sum - vector_b[i]); | |
| 169 | } | ||
| 170 | |||
| 171 | 6 | residual_norm /= static_cast<double>(system_size_); | |
| 172 | |||
| 173 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | return residual_norm < (epsilon_ * 1000.0); |
| 174 | 6 | } catch (...) { | |
| 175 | return false; | ||
| 176 | ✗ | } | |
| 177 | } | ||
| 178 | |||
| 179 | } // namespace zaharov_g_seidel_int_met | ||
| 180 |