GCC Code Coverage Report


Directory: ./
File: tasks/liulin_y_vert_strip_diag_matrix_vect_mult/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 74 75 98.7%
Functions: 8 8 100.0%
Branches: 52 82 63.4%

Line Branch Exec Source
1 #include "liulin_y_vert_strip_diag_matrix_vect_mult/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstddef>
6 #include <vector>
7
8 #include "liulin_y_vert_strip_diag_matrix_vect_mult/common/include/common.hpp"
9
10 namespace liulin_y_vert_strip_diag_matrix_vect_mult {
11
12
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 LiulinYVertStripDiagMatrixVectMultMPI::LiulinYVertStripDiagMatrixVectMultMPI(const InType &in) {
13 SetTypeOfTask(GetStaticTypeOfTask());
14
15 auto &matrix = std::get<0>(GetInput());
16 auto &vect = std::get<1>(GetInput());
17
18 const auto &input_matrix = std::get<0>(in);
19 const auto &input_vect = std::get<1>(in);
20
21 matrix.clear();
22 vect.clear();
23
24
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (!input_matrix.empty()) {
25
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 matrix = input_matrix;
26 }
27
28
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (!input_vect.empty()) {
29
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 vect = input_vect;
30 }
31
32 GetOutput().clear();
33 20 }
34
35 20 bool LiulinYVertStripDiagMatrixVectMultMPI::ValidationImpl() {
36 20 int world_rank = 0;
37 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
38
39 if (world_rank != 0) {
40 return true;
41 }
42 return true;
43 }
44 20 bool LiulinYVertStripDiagMatrixVectMultMPI::PreProcessingImpl() {
45 20 return true;
46 }
47
48 namespace {
49 20 void PrepareCounts(int rows, int cols, int world_size, std::vector<int> &sendcounts, std::vector<int> &displs) {
50 20 sendcounts.assign(world_size, 0);
51 20 displs.assign(world_size, 0);
52
53 20 int base_cols = cols / world_size;
54 20 int remainder = cols % world_size;
55
56
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int proc = 0; proc < world_size; ++proc) {
57
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 14 times.
40 int local_cols = base_cols + (proc < remainder ? 1 : 0);
58
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 sendcounts[proc] = local_cols * rows;
59
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (proc > 0) {
60 20 displs[proc] = displs[proc - 1] + sendcounts[proc - 1];
61 }
62 }
63 20 }
64
65 10 void FillFlatMatrix(const std::vector<std::vector<int>> &matrix, int rows, int cols, std::vector<int> &flat_matrix) {
66 10 flat_matrix.resize(static_cast<std::size_t>(rows) * static_cast<std::size_t>(cols));
67
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 10 times.
37 for (int col = 0; col < cols; ++col) {
68
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 27 times.
91 for (int row = 0; row < rows; ++row) {
69 64 flat_matrix[(col * rows) + row] = matrix[row][col];
70 }
71 }
72 10 }
73
74 20 std::vector<int> ComputeLocalPartialRes(const std::vector<int> &local_data, const std::vector<int> &local_vect,
75 int rows, int local_cols) {
76 20 std::vector<int> local_partial(rows, 0);
77
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 20 times.
47 for (int col_idx = 0; col_idx < local_cols; ++col_idx) {
78
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 27 times.
91 for (int row = 0; row < rows; ++row) {
79 64 local_partial[row] += local_data[(col_idx * rows) + row] * local_vect[col_idx];
80 }
81 }
82 20 return local_partial;
83 }
84 } // namespace
85
86 20 bool LiulinYVertStripDiagMatrixVectMultMPI::RunImpl() {
87 const auto &input = GetInput();
88 auto &out = GetOutput();
89
90 20 int world_size = 0;
91 20 int world_rank = 0;
92 20 MPI_Comm_size(MPI_COMM_WORLD, &world_size);
93 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
94
95 20 int rows = 0;
96 20 int cols = 0;
97
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
98 const auto &matrix = std::get<0>(input);
99
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (!matrix.empty() && !matrix[0].empty()) {
100 10 rows = static_cast<int>(matrix.size());
101 10 cols = static_cast<int>(matrix[0].size());
102 }
103 }
104
105 20 MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
106 20 MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD);
107
108
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
20 if (rows <= 0 || cols <= 0) {
109 out.clear();
110 return true;
111 }
112
113 20 out.assign(rows, 0);
114
115 20 std::vector<int> sendcounts;
116 20 std::vector<int> displs;
117
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 PrepareCounts(rows, cols, world_size, sendcounts, displs);
118
119
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> recvcounts(world_size);
120
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> displs_gather(world_size, 0);
121
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int proc = 0; proc < world_size; ++proc) {
122
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 recvcounts[proc] = sendcounts[proc] / rows;
123
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (proc > 0) {
124 20 displs_gather[proc] = displs_gather[proc - 1] + recvcounts[proc - 1];
125 }
126 }
127
128
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 int local_cols = recvcounts[world_rank];
129 20 int local_elements = local_cols * rows;
130
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> local_data(local_elements);
131
132 20 std::vector<int> flat_matrix;
133
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
134 const auto &matrix = std::get<0>(input);
135
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 FillFlatMatrix(matrix, rows, cols, flat_matrix);
136 }
137
138
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
30 MPI_Scatterv(world_rank == 0 ? flat_matrix.data() : nullptr, sendcounts.data(), displs.data(), MPI_INT,
139 local_data.data(), local_elements, MPI_INT, 0, MPI_COMM_WORLD);
140
141
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> local_vect(local_cols);
142
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
143 const auto &vect = std::get<1>(input);
144
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Scatterv(vect.data(), recvcounts.data(), displs_gather.data(), MPI_INT, local_vect.data(), local_cols, MPI_INT,
145 0, MPI_COMM_WORLD);
146 } else {
147
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Scatterv(nullptr, recvcounts.data(), displs_gather.data(), MPI_INT, local_vect.data(), local_cols, MPI_INT, 0,
148 MPI_COMM_WORLD);
149 }
150
151
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<int> local_partial = ComputeLocalPartialRes(local_data, local_vect, rows, local_cols);
152
153
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Reduce(local_partial.data(), out.data(), rows, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
154
155
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Bcast(out.data(), rows, MPI_INT, 0, MPI_COMM_WORLD);
156
157 return true;
158 }
159
160 20 bool LiulinYVertStripDiagMatrixVectMultMPI::PostProcessingImpl() {
161 20 return true;
162 }
163
164 } // namespace liulin_y_vert_strip_diag_matrix_vect_mult
165