| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "kopilov_d_sum_val_col_mat/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <cstddef> | ||
| 6 | #include <utility> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "kopilov_d_sum_val_col_mat/common/include/common.hpp" | ||
| 10 | |||
| 11 | namespace kopilov_d_sum_val_col_mat { | ||
| 12 | |||
| 13 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | KopilovDSumValColMatMPI::KopilovDSumValColMatMPI(const InType &in) { |
| 14 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 15 | GetInput() = in; | ||
| 16 | 6 | GetOutput() = OutType{}; | |
| 17 | 6 | } | |
| 18 | |||
| 19 | 6 | bool KopilovDSumValColMatMPI::ValidationImpl() { | |
| 20 | 6 | return true; | |
| 21 | } | ||
| 22 | |||
| 23 | 6 | bool KopilovDSumValColMatMPI::PreProcessingImpl() { | |
| 24 | 6 | return true; | |
| 25 | } | ||
| 26 | |||
| 27 | 6 | bool KopilovDSumValColMatMPI::RunImpl() { | |
| 28 | 6 | int world_rank = 0; | |
| 29 | 6 | int world_size = 1; | |
| 30 | 6 | MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); | |
| 31 | 6 | MPI_Comm_size(MPI_COMM_WORLD, &world_size); | |
| 32 | |||
| 33 | 6 | int rows = 0; | |
| 34 | 6 | int cols = 0; | |
| 35 | const double *send_buffer_ptr = nullptr; | ||
| 36 | |||
| 37 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (world_rank == 0) { |
| 38 | 3 | rows = GetInput().rows; | |
| 39 | 3 | cols = GetInput().cols; | |
| 40 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | const std::size_t expected_size = static_cast<std::size_t>(rows) * static_cast<std::size_t>(cols); |
| 41 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (GetInput().data.size() != expected_size) { |
| 42 | return false; | ||
| 43 | } | ||
| 44 | send_buffer_ptr = GetInput().data.data(); | ||
| 45 | } | ||
| 46 | |||
| 47 | 6 | MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 48 | 6 | MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 49 | |||
| 50 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (rows == 0 || cols == 0) { |
| 51 | GetOutput().col_sum.clear(); | ||
| 52 | ✗ | return true; | |
| 53 | } | ||
| 54 | |||
| 55 | // compute rows per process (by rows, not by elements) to avoid fractional rows | ||
| 56 | 6 | std::vector<int> rows_per_rank(static_cast<std::size_t>(world_size), 0); | |
| 57 | 6 | const int base_rows = rows / world_size; | |
| 58 | 6 | const int remainder_rows = rows % world_size; | |
| 59 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | for (int pid = 0; pid < world_size; ++pid) { |
| 60 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
18 | rows_per_rank[static_cast<std::size_t>(pid)] = base_rows + (pid < remainder_rows ? 1 : 0); |
| 61 | } | ||
| 62 | |||
| 63 | // send_counts/displs are in number of doubles (elements) | ||
| 64 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<int> send_counts(static_cast<std::size_t>(world_size), 0); |
| 65 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<int> displacements(static_cast<std::size_t>(world_size), 0); |
| 66 | int offset = 0; | ||
| 67 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | for (int pid = 0; pid < world_size; ++pid) { |
| 68 | 12 | send_counts[static_cast<std::size_t>(pid)] = rows_per_rank[static_cast<std::size_t>(pid)] * cols; | |
| 69 | 12 | displacements[static_cast<std::size_t>(pid)] = offset; | |
| 70 | 12 | offset += send_counts[static_cast<std::size_t>(pid)]; | |
| 71 | } | ||
| 72 | |||
| 73 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | const int recv_count = send_counts[static_cast<std::size_t>(world_rank)]; |
| 74 |
2/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
6 | std::vector<double> recv_buffer(static_cast<std::size_t>(recv_count), 0.0); |
| 75 | |||
| 76 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Scatterv(send_buffer_ptr, send_counts.data(), displacements.data(), MPI_DOUBLE, recv_buffer.data(), recv_count, |
| 77 | MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
| 78 | |||
| 79 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | const int local_rows = (cols == 0) ? 0 : static_cast<int>(recv_buffer.size()) / cols; |
| 80 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> local_col_sum(static_cast<std::size_t>(cols), 0.0); |
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6 times.
|
21 | for (int row = 0; row < local_rows; ++row) { |
| 83 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 15 times.
|
98 | for (int col = 0; col < cols; ++col) { |
| 84 | 83 | local_col_sum[static_cast<std::size_t>(col)] += | |
| 85 | 83 | recv_buffer[(static_cast<std::size_t>(row) * static_cast<std::size_t>(cols)) + static_cast<std::size_t>(col)]; | |
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6 | std::vector<double> global_col_sum(static_cast<std::size_t>(cols), 0.0); |
| 90 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Reduce(local_col_sum.data(), global_col_sum.data(), cols, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); |
| 91 | |||
| 92 | // Broadcast result to all processes so tests can validate on any rank | ||
| 93 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | MPI_Bcast(global_col_sum.data(), cols, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 94 | |||
| 95 | 6 | GetOutput().col_sum = std::move(global_col_sum); | |
| 96 | |||
| 97 | return true; | ||
| 98 | } | ||
| 99 | |||
| 100 | 6 | bool KopilovDSumValColMatMPI::PostProcessingImpl() { | |
| 101 | 6 | return true; | |
| 102 | } | ||
| 103 | |||
| 104 | } // namespace kopilov_d_sum_val_col_mat | ||
| 105 |