GCC Code Coverage Report


Directory: ./
File: tasks/chaschin_v_max_for_each_row/mpi/src/ops_mpi.cpp
Date: 2025-12-13 04:24:21
Exec Total Coverage
Lines: 88 89 98.9%
Functions: 11 11 100.0%
Branches: 53 72 73.6%

Line Branch Exec Source
1 #include "chaschin_v_max_for_each_row/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <limits>
8 #include <utility>
9 #include <vector>
10
11 #include "chaschin_v_max_for_each_row/common/include/common.hpp"
12
13 namespace chaschin_v_max_for_each_row {
14
15
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 ChaschinVMaxForEachRow::ChaschinVMaxForEachRow(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 auto in_copy = in;
18 40 GetInput() = std::move(in_copy);
19 this->GetOutput().clear();
20 40 }
21
22 40 bool ChaschinVMaxForEachRow::ValidationImpl() {
23 const auto &in = GetInput();
24
25 if (in.empty()) {
26 return in.empty();
27 }
28
29 if (in[0].empty()) {
30 return in[0].empty();
31 }
32
33 return true;
34 }
35
36 40 bool ChaschinVMaxForEachRow::PreProcessingImpl() {
37 40 return true;
38 }
39
40 20 void chaschin_v_max_for_each_row::ChaschinVMaxForEachRow::SendRowsToWorkers(const std::vector<std::vector<float>> &mat,
41 int size) {
42
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 for (int pi = 1; pi < size; ++pi) {
43 // Inline ComputeRange
44 20 int nrows = static_cast<int>(mat.size());
45 20 int base = nrows / size;
46 20 int rem = nrows % size;
47
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 int start = (pi * base) + std::min(pi, rem);
48
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 int count = base + (pi < rem ? 1 : 0);
49
50
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 20 times.
44 for (int ii = 0; ii < count; ++ii) {
51 24 const auto &row = mat[start + ii];
52 24 int len = static_cast<int>(row.size());
53
54 24 MPI_Send(&len, 1, MPI_INT, pi, 100, MPI_COMM_WORLD);
55
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len > 0) {
56 24 MPI_Send(row.data(), len, MPI_FLOAT, pi, 101, MPI_COMM_WORLD);
57 }
58 }
59 }
60 20 }
61
62 20 void chaschin_v_max_for_each_row::ChaschinVMaxForEachRow::ReceiveRowsFromRoot(
63 std::vector<std::vector<float>> &local_mat) {
64
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 20 times.
44 for (auto &row : local_mat) {
65 24 int len = 0;
66 24 MPI_Recv(&len, 1, MPI_INT, 0, 100, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
67
68 24 row.resize(len);
69
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (len > 0) {
70 24 MPI_Recv(row.data(), len, MPI_FLOAT, 0, 101, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
71 }
72 }
73 20 }
74
75 40 std::vector<std::vector<float>> chaschin_v_max_for_each_row::ChaschinVMaxForEachRow::DistributeRows(
76 const std::vector<std::vector<float>> &mat, int rank, int size, const RowRange &range) {
77 40 std::vector<std::vector<float>> local_mat(range.count);
78
79
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank == 0) {
80
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 SendRowsToWorkers(mat, size);
81
82
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int ii = 0; ii < range.count; ++ii) {
83
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 local_mat[ii] = mat[range.start + ii];
84 }
85 } else {
86
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ReceiveRowsFromRoot(local_mat);
87 }
88
89 40 return local_mat;
90 }
91
92 40 std::vector<float> chaschin_v_max_for_each_row::ChaschinVMaxForEachRow::ComputeLocalMax(
93 const std::vector<std::vector<float>> &local_mat) {
94 40 std::vector<float> local_out(local_mat.size());
95
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 40 times.
104 for (size_t ii = 0; ii < local_mat.size(); ++ii) {
96
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
128 local_out[ii] = local_mat[ii].empty() ? std::numeric_limits<float>::lowest()
97 : *std::max_element(local_mat[ii].begin(), local_mat[ii].end());
98 }
99 40 return local_out;
100 }
101
102 namespace {
103 inline void GetRangeForRank(int rank, int total, int world_size, int &start, int &count) {
104 20 int base = total / world_size;
105 20 int rem = total % world_size;
106
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 start = (rank * base) + std::min(rank, rem);
107
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 count = base + (rank < rem ? 1 : 0);
108 }
109
110 12 inline void RecvRows(int src_rank, std::vector<float> &out, int start, int count) {
111
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 std::vector<float> tmp(count);
112
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Recv(tmp.data(), count, MPI_FLOAT, src_rank, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
113 std::ranges::copy(tmp, out.begin() + start);
114 12 }
115 } // namespace
116
117 40 void chaschin_v_max_for_each_row::ChaschinVMaxForEachRow::GatherResults(std::vector<float> &out,
118 const std::vector<float> &local_out, int rank,
119 int size, const RowRange &range) {
120
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank != 0) {
121
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
20 if (!local_out.empty()) {
122 12 MPI_Send(local_out.data(), static_cast<int>(local_out.size()), MPI_FLOAT, 0, 2, MPI_COMM_WORLD);
123 }
124 20 return;
125 }
126
127
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int i = 0; i < range.count; ++i) {
128 40 out[range.start + i] = local_out[i];
129 }
130
131 20 int total = static_cast<int>(out.size());
132
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 for (int pi = 1; pi < size; ++pi) {
133 int start = 0;
134 int count = 0;
135
136 GetRangeForRank(pi, total, size, start, count);
137
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
20 if (count > 0) {
138 12 RecvRows(pi, out, start, count);
139 }
140 }
141 }
142
143 40 bool ChaschinVMaxForEachRow::RunImpl() {
144 40 int rank = 0;
145 40 int size = 0;
146 40 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
147 40 MPI_Comm_size(MPI_COMM_WORLD, &size);
148
149 const auto &mat = GetInput();
150
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 int nrows = (rank == 0) ? static_cast<int>(mat.size()) : 0;
151 40 MPI_Bcast(&nrows, 1, MPI_INT, 0, MPI_COMM_WORLD);
152
153 40 int base = nrows / size;
154 40 int rem = nrows % size;
155
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 int start = (rank * base) + std::min(rank, rem);
156
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 int count = base + (rank < rem ? 1 : 0);
157 40 RowRange range{.start = start, .count = count};
158
159 40 auto local_mat = DistributeRows(mat, rank, size, range);
160
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 auto local_out = ComputeLocalMax(local_mat);
161
162
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank == 0) {
163
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetOutput().resize(nrows);
164 }
165
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 GatherResults(GetOutput(), local_out, rank, size, range);
166
167 auto &out = GetOutput();
168
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank != 0) {
169
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 out.resize(nrows);
170 }
171
172
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
40 if (nrows > 0) {
173
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Bcast(out.data(), nrows, MPI_FLOAT, 0, MPI_COMM_WORLD);
174 }
175
176 40 return true;
177 40 }
178
179 40 bool ChaschinVMaxForEachRow::PostProcessingImpl() {
180 40 int rank = 0;
181 40 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
182 40 return true;
183 }
184 } // namespace chaschin_v_max_for_each_row
185