GCC Code Coverage Report


Directory: ./
File: tasks/chernov_t_ribbon_horizontal_a_matrix_mult/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 103 105 98.1%
Functions: 10 10 100.0%
Branches: 57 90 63.3%

Line Branch Exec Source
1 #include "chernov_t_ribbon_horizontal_a_matrix_mult/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <array>
6 #include <cstddef>
7 #include <vector>
8
9 #include "chernov_t_ribbon_horizontal_a_matrix_mult/common/include/common.hpp"
10
11 namespace chernov_t_ribbon_horizontal_a_matrix_mult {
12
13
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ChernovTRibbonHorizontalAMmatrixMultMPI::ChernovTRibbonHorizontalAMmatrixMultMPI(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 4 GetOutput() = std::vector<int>();
17 4 }
18
19 4 bool ChernovTRibbonHorizontalAMmatrixMultMPI::ValidationImpl() {
20 const auto &input = GetInput();
21
22 4 int rows_a = std::get<0>(input);
23 4 int cols_a = std::get<1>(input);
24 const auto &vec_a = std::get<2>(input);
25
26 4 int rows_b = std::get<3>(input);
27 4 int cols_b = std::get<4>(input);
28 const auto &vec_b = std::get<5>(input);
29
30
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 valid_ = (cols_a == rows_b) && (vec_a.size() == static_cast<size_t>(rows_a) * static_cast<size_t>(cols_a)) &&
31
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 (vec_b.size() == static_cast<size_t>(rows_b) * static_cast<size_t>(cols_b)) && (rows_a > 0) &&
32
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 (cols_a > 0) && (rows_b > 0) && (cols_b > 0);
33
34 4 return valid_;
35 }
36
37 4 bool ChernovTRibbonHorizontalAMmatrixMultMPI::PreProcessingImpl() {
38 4 int rank = 0;
39 4 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
40
41
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!valid_) {
42 return false;
43 }
44
45
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank == 0) {
46 const auto &input = GetInput();
47
48 2 rowsA_ = std::get<0>(input);
49 2 colsA_ = std::get<1>(input);
50 2 matrixA_ = std::get<2>(input);
51
52 2 rowsB_ = std::get<3>(input);
53 2 colsB_ = std::get<4>(input);
54 2 matrixB_ = std::get<5>(input);
55 }
56
57 return true;
58 }
59
60 4 bool ChernovTRibbonHorizontalAMmatrixMultMPI::RunImpl() {
61 4 int rank = 0;
62 4 int size = 0;
63 4 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
64 4 MPI_Comm_size(MPI_COMM_WORLD, &size);
65
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!valid_) {
67 GetOutput() = std::vector<int>();
68 return false;
69 }
70
71 4 BroadcastMatrixSizes(rank);
72
73 4 BroadcastMatrixB(rank);
74
75 4 std::vector<int> local_a = ScatterMatrixA(rank, size);
76
77 4 int base_rows = global_rowsA_ / size;
78 4 int remainder = global_rowsA_ % size;
79
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 int local_rows = base_rows + (rank < remainder ? 1 : 0);
80
81
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 std::vector<int> local_c = ComputeLocalC(local_rows, local_a);
82
83
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 GatherResult(rank, size, local_c);
84
85 return true;
86 }
87
88 4 void ChernovTRibbonHorizontalAMmatrixMultMPI::BroadcastMatrixSizes(int rank) {
89 4 std::array<int, 4> sizes{};
90
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank == 0) {
91 2 sizes[0] = rowsA_;
92 2 sizes[1] = colsA_;
93 2 sizes[2] = rowsB_;
94 2 sizes[3] = colsB_;
95 }
96
97 4 MPI_Bcast(sizes.data(), sizes.size(), MPI_INT, 0, MPI_COMM_WORLD);
98 4 global_rowsA_ = sizes[0];
99 4 global_colsA_ = sizes[1];
100 4 global_rowsB_ = sizes[2];
101 4 global_colsB_ = sizes[3];
102 4 }
103
104 4 void ChernovTRibbonHorizontalAMmatrixMultMPI::BroadcastMatrixB(int rank) {
105
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank != 0) {
106 2 matrixB_.resize(static_cast<size_t>(global_rowsB_) * static_cast<size_t>(global_colsB_));
107 }
108 4 MPI_Bcast(matrixB_.data(), global_rowsB_ * global_colsB_, MPI_INT, 0, MPI_COMM_WORLD);
109 4 }
110
111 4 std::vector<int> ChernovTRibbonHorizontalAMmatrixMultMPI::ScatterMatrixA(int rank, int size) {
112 4 int base_rows = global_rowsA_ / size;
113 4 int remainder = global_rowsA_ % size;
114
115
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 int local_rows = base_rows + (rank < remainder ? 1 : 0);
116 4 int local_elements = static_cast<int>(static_cast<size_t>(local_rows) * static_cast<size_t>(global_colsA_));
117
118 4 std::vector<int> local_a(local_elements);
119
1/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 std::vector<int> sendcounts(size);
120
1/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 std::vector<int> displacements(size);
121
122
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank == 0) {
123 int offset = 0;
124
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i++) {
125
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 int rows_for_i = base_rows + (i < remainder ? 1 : 0);
126 4 sendcounts[i] = rows_for_i * global_colsA_;
127 4 displacements[i] = offset;
128 4 offset += sendcounts[i];
129 }
130 }
131
132
1/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 std::vector<int> recvcounts(size);
133
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank == 0) {
134
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 recvcounts = sendcounts;
135 }
136
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Bcast(recvcounts.data(), size, MPI_INT, 0, MPI_COMM_WORLD);
137
138
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
6 MPI_Scatterv(rank == 0 ? matrixA_.data() : nullptr, rank == 0 ? sendcounts.data() : nullptr,
139 rank == 0 ? displacements.data() : nullptr, MPI_INT, local_a.data(), local_elements, MPI_INT, 0,
140 MPI_COMM_WORLD);
141
142 4 return local_a;
143 }
144
145 4 std::vector<int> ChernovTRibbonHorizontalAMmatrixMultMPI::ComputeLocalC(int local_rows,
146 const std::vector<int> &local_a) {
147 4 std::vector<int> local_c(static_cast<size_t>(local_rows) * static_cast<size_t>(global_colsB_), 0);
148
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 for (int i = 0; i < local_rows; i++) {
149
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5 times.
23 for (int j = 0; j < global_colsB_; j++) {
150 int sum = 0;
151
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 18 times.
60 for (int k = 0; k < global_colsA_; k++) {
152 42 sum += local_a[(i * global_colsA_) + k] * matrixB_[(k * global_colsB_) + j];
153 }
154 18 local_c[(i * global_colsB_) + j] = sum;
155 }
156 }
157 4 return local_c;
158 }
159
160 4 void ChernovTRibbonHorizontalAMmatrixMultMPI::GatherResult(int rank, int size, const std::vector<int> &local_c) {
161 4 int base_rows = global_rowsA_ / size;
162 4 int remainder = global_rowsA_ % size;
163
164 4 std::vector<int> recvcounts(size);
165
1/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 std::vector<int> displacements(size);
166
167
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (rank == 0) {
168 int offset = 0;
169
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < size; i++) {
170
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 int rows_for_i = base_rows + (i < remainder ? 1 : 0);
171 4 recvcounts[i] = rows_for_i * global_colsB_;
172 4 displacements[i] = offset;
173 4 offset += recvcounts[i];
174 }
175 }
176
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Bcast(recvcounts.data(), size, MPI_INT, 0, MPI_COMM_WORLD);
177
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Bcast(displacements.data(), size, MPI_INT, 0, MPI_COMM_WORLD);
178
179
2/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 std::vector<int> result(static_cast<size_t>(global_rowsA_) * static_cast<size_t>(global_colsB_));
180
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Gatherv(local_c.data(), static_cast<int>(local_c.size()), MPI_INT, result.data(), recvcounts.data(),
181 displacements.data(), MPI_INT, 0, MPI_COMM_WORLD);
182
183
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MPI_Bcast(result.data(), global_rowsA_ * global_colsB_, MPI_INT, 0, MPI_COMM_WORLD);
184
185
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 GetOutput() = result;
186 4 }
187
188
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 bool ChernovTRibbonHorizontalAMmatrixMultMPI::PostProcessingImpl() {
189 matrixA_.clear();
190 matrixB_.clear();
191
192 4 return true;
193 }
194
195 } // namespace chernov_t_ribbon_horizontal_a_matrix_mult
196