GCC Code Coverage Report


Directory: ./
File: tasks/ivanova_p_max_matrix/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 63 63 100.0%
Functions: 6 6 100.0%
Branches: 36 56 64.3%

Line Branch Exec Source
1 #include "ivanova_p_max_matrix/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cstring> // memcpy
7 #include <limits>
8 #include <vector>
9
10 #include "ivanova_p_max_matrix/common/include/common.hpp"
11
12 namespace ivanova_p_max_matrix {
13
14
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 IvanovaPMaxMatrixMPI::IvanovaPMaxMatrixMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16 12 GetOutput() = std::numeric_limits<int>::min();
17
18 12 int rank = 0;
19
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
20
21
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
22
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 GetInput() = in; // Только root хранит входную матрицу
23 } else {
24 GetInput().clear(); // Остальные — пустая матрица
25 }
26 12 }
27
28 12 bool IvanovaPMaxMatrixMPI::ValidationImpl() {
29 12 int rank = 0;
30 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
31
32 bool ok = true;
33
34
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GetInput().empty()) {
36 ok = false;
37 } else {
38 const size_t cols = GetInput()[0].size();
39
2/2
✓ Branch 0 taken 1788 times.
✓ Branch 1 taken 6 times.
1794 for (const auto &row : GetInput()) {
40
1/2
✓ Branch 0 taken 1788 times.
✗ Branch 1 not taken.
1788 if (row.size() != cols) {
41 ok = false;
42 break;
43 }
44 }
45 }
46 }
47
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int ok_int = ok ? 1 : 0;
49 12 MPI_Bcast(&ok_int, 1, MPI_INT, 0, MPI_COMM_WORLD);
50 12 return ok_int != 0;
51 }
52
53 12 bool IvanovaPMaxMatrixMPI::PreProcessingImpl() {
54 12 GetOutput() = std::numeric_limits<int>::min();
55 12 return true;
56 }
57
58 namespace {
59
60 6 std::vector<int> PackMatrix(const InType &input, int rows, int cols) {
61 6 std::vector<int> flat(static_cast<size_t>(rows) * cols);
62
63 size_t pos = 0;
64
2/2
✓ Branch 0 taken 1788 times.
✓ Branch 1 taken 6 times.
1794 for (int i = 0; i < rows; ++i) {
65 // быстрее, чем двойной for: memcpy целой строки
66 1788 std::memcpy(&flat[pos], input[i].data(), sizeof(int) * cols);
67 1788 pos += cols;
68 }
69 6 return flat;
70 }
71
72 int FindLocalMax(const std::vector<int> &vec) {
73
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (vec.empty()) {
74 return std::numeric_limits<int>::min();
75 }
76 12 return *std::ranges::max_element(vec);
77 }
78
79 } // namespace
80
81 12 bool IvanovaPMaxMatrixMPI::RunImpl() {
82 12 int rank = 0;
83 12 int size = 1;
84 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
85 12 MPI_Comm_size(MPI_COMM_WORLD, &size);
86
87 12 int rows = 0;
88 12 int cols = 0;
89
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
90 6 rows = static_cast<int>(GetInput().size());
91
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 cols = rows > 0 ? static_cast<int>(GetInput()[0].size()) : 0;
92 }
93
94 12 MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
95 12 MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD);
96
97 12 const int total = rows * cols;
98
99 12 int base = total / size;
100 12 int rem = total % size;
101
102
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 int my_count = base + (rank < rem ? 1 : 0);
103
104 12 std::vector<int> sendcounts(size);
105
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);
106
107
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int rank_idx = 0; rank_idx < size; rank_idx++) {
108
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 sendcounts[rank_idx] = base + (rank_idx < rem ? 1 : 0);
109 }
110
111 12 displs[0] = 0;
112
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int rank_idx = 1; rank_idx < size; rank_idx++) {
113 12 displs[rank_idx] = displs[rank_idx - 1] + sendcounts[rank_idx - 1];
114 }
115
116 12 std::vector<int> flat;
117
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
118
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 flat = PackMatrix(GetInput(), rows, cols);
119 }
120
121
3/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
12 std::vector<int> local(my_count);
122
123
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
18 MPI_Scatterv(rank == 0 ? flat.data() : nullptr, sendcounts.data(), displs.data(), MPI_INT, local.data(), my_count,
124 MPI_INT, 0, MPI_COMM_WORLD);
125
126 12 int local_max = FindLocalMax(local);
127
128 12 int global_max = 0;
129
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allreduce(&local_max, &global_max, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
130
131
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 GetOutput() = global_max;
132 12 return true;
133 }
134
135 12 bool IvanovaPMaxMatrixMPI::PostProcessingImpl() {
136 12 return true;
137 }
138
139 } // namespace ivanova_p_max_matrix
140