GCC Code Coverage Report


Directory: ./
File: tasks/yakimov_i_max_values_in_matrix_rows/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 0 121 0.0%
Functions: 0 11 0.0%
Branches: 0 112 0.0%

Line Branch Exec Source
1 #include "yakimov_i_max_values_in_matrix_rows/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstddef>
8 #include <filesystem>
9 #include <fstream>
10 #include <iostream>
11 #include <string>
12 #include <vector>
13
14 // #include "util/include/util.hpp"
15 #include "yakimov_i_max_values_in_matrix_rows/common/include/common.hpp"
16
17 namespace yakimov_i_max_values_in_matrix_rows {
18
19 namespace {
20 void CalculateLocalRows(int rank, int size, int total_rows, int &local_rows, int &start_row, int &end_row) {
21 int rows_per_process = total_rows / size;
22 int remainder = total_rows % size;
23
24 start_row = (rank * rows_per_process) + std::min(rank, remainder);
25 end_row = start_row + rows_per_process + (rank < remainder ? 1 : 0);
26 local_rows = end_row - start_row;
27 }
28
29 void FindLocalMaxValues(int local_rows, int total_cols, const std::vector<InType> &local_data,
30 std::vector<InType> &local_max_values) {
31 for (int i = 0; i < local_rows; i++) {
32 InType row_max = local_data[static_cast<size_t>(i) * static_cast<size_t>(total_cols)];
33 for (int j = 1; j < total_cols; j++) {
34 row_max = std::max(local_data[(i * total_cols) + j], row_max);
35 }
36 local_max_values[i] = row_max;
37 }
38 }
39 } // namespace
40
41 bool YakimovIMaxValuesInMatrixRowsMPI::ValidationImpl() {
42 int rank = 0;
43 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
44 if (rank == 0) {
45 return (GetInput() > 0);
46 }
47 return true;
48 }
49
50 void YakimovIMaxValuesInMatrixRowsMPI::SendDataToWorkers(int size, int total_rows, int total_cols) {
51 int rows_per_process = total_rows / size;
52 int remainder = total_rows % size;
53
54 for (int proc = 1; proc < size; proc++) {
55 int proc_start = (proc * rows_per_process) + std::min(proc, remainder);
56 int proc_rows = rows_per_process + (proc < remainder ? 1 : 0);
57
58 std::vector<InType> proc_data;
59 proc_data.reserve(static_cast<size_t>(proc_rows) * static_cast<size_t>(total_cols));
60 for (int i = 0; i < proc_rows; i++) {
61 proc_data.insert(proc_data.end(), matrix_[proc_start + i].begin(), matrix_[proc_start + i].end());
62 }
63
64 MPI_Send(proc_data.data(), proc_rows * total_cols, MPI_INT, proc, 0, MPI_COMM_WORLD);
65 }
66 }
67
68 void YakimovIMaxValuesInMatrixRowsMPI::ProcessLocalData(int rank, int local_rows, int total_cols, int start_row,
69 std::vector<InType> &local_data) {
70 if (rank == 0) {
71 local_data.reserve(static_cast<size_t>(local_rows) * static_cast<size_t>(total_cols));
72 for (int i = 0; i < local_rows; i++) {
73 local_data.insert(local_data.end(), matrix_[start_row + i].begin(), matrix_[start_row + i].end());
74 }
75 } else {
76 local_data.resize(static_cast<size_t>(local_rows) * static_cast<size_t>(total_cols));
77 MPI_Recv(local_data.data(), local_rows * total_cols, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
78 }
79 }
80
81 void YakimovIMaxValuesInMatrixRowsMPI::GatherResults(int rank, int size, int total_rows,
82 const std::vector<InType> &local_max_values, int start_row,
83 int local_rows) {
84 int rows_per_process = total_rows / size;
85 int remainder = total_rows % size;
86
87 if (rank == 0) {
88 max_Values_.resize(total_rows);
89
90 for (int i = 0; i < local_rows; i++) {
91 max_Values_[start_row + i] = local_max_values[i];
92 }
93
94 for (int proc = 1; proc < size; proc++) {
95 int proc_start = (proc * rows_per_process) + std::min(proc, remainder);
96 int proc_rows = rows_per_process + (proc < remainder ? 1 : 0);
97
98 std::vector<InType> proc_max_values(proc_rows);
99 MPI_Recv(proc_max_values.data(), proc_rows, MPI_INT, proc, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
100
101 for (int i = 0; i < proc_rows; i++) {
102 max_Values_[proc_start + i] = proc_max_values[i];
103 }
104 }
105 } else {
106 MPI_Send(local_max_values.data(), local_rows, MPI_INT, 0, 0, MPI_COMM_WORLD);
107 }
108 }
109
110 bool YakimovIMaxValuesInMatrixRowsMPI::PostProcessingImpl() {
111 int rank = 0;
112 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
113
114 if (rank == 0) {
115 if (!max_Values_.empty()) {
116 OutType result = 0;
117 for (const auto &max_val : max_Values_) {
118 result += max_val;
119 }
120 GetOutput() = result;
121 } else {
122 return false;
123 }
124 } else {
125 GetOutput() = 0;
126 }
127
128 OutType final_result = GetOutput();
129 MPI_Bcast(&final_result, 1, MPI_INT, 0, MPI_COMM_WORLD);
130 GetOutput() = final_result;
131
132 return true;
133 }
134
135 YakimovIMaxValuesInMatrixRowsMPI::YakimovIMaxValuesInMatrixRowsMPI(const InType &in) {
136 SetTypeOfTask(GetStaticTypeOfTask());
137 GetInput() = in;
138 GetOutput() = 0;
139 std::filesystem::path base_path = std::filesystem::current_path();
140 while (base_path.filename() != "ppc-2025-processes-engineers") {
141 base_path = base_path.parent_path();
142 }
143 matrix_Filename_ =
144 base_path.string() + "/tasks/yakimov_i_max_values_in_matrix_rows/data/" + std::to_string(GetInput()) + ".txt";
145 }
146
147 bool YakimovIMaxValuesInMatrixRowsMPI::PreProcessingImpl() {
148 int rank = 0;
149 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
150
151 if (rank == 0) {
152 if (!ReadMatrixFromFile(matrix_Filename_)) {
153 return false;
154 }
155
156 max_Values_.resize(rows_, 0);
157 }
158
159 MPI_Barrier(MPI_COMM_WORLD);
160 return true;
161 }
162
163 bool YakimovIMaxValuesInMatrixRowsMPI::ReadMatrixFromFile(const std::string &filename) {
164 std::ifstream file(filename);
165 if (!file.is_open()) {
166 return false;
167 }
168
169 file >> rows_ >> cols_;
170
171 if (rows_ == 0 || cols_ == 0) {
172 return false;
173 }
174
175 matrix_.resize(rows_);
176 for (size_t i = 0; i < rows_; i++) {
177 matrix_[i].resize(cols_);
178 }
179
180 for (size_t i = 0; i < rows_; i++) {
181 for (size_t j = 0; j < cols_; j++) {
182 if (!(file >> matrix_[i][j])) {
183 return false;
184 }
185 }
186 }
187
188 file.close();
189 return true;
190 }
191
192 void YakimovIMaxValuesInMatrixRowsMPI::BroadcastMatrixDimensions(int &total_rows, int &total_cols) const {
193 std::array<int, 2> matrix_dims = {0, 0};
194 int rank = 0;
195 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
196
197 if (rank == 0) {
198 matrix_dims[0] = static_cast<int>(rows_);
199 matrix_dims[1] = static_cast<int>(cols_);
200 }
201
202 MPI_Bcast(matrix_dims.data(), 2, MPI_INT, 0, MPI_COMM_WORLD);
203 total_rows = matrix_dims[0];
204 total_cols = matrix_dims[1];
205 }
206
207 bool YakimovIMaxValuesInMatrixRowsMPI::RunImpl() {
208 int rank = 0;
209 int size = 0;
210 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
211 MPI_Comm_size(MPI_COMM_WORLD, &size);
212
213 int total_rows = 0;
214 int total_cols = 0;
215 BroadcastMatrixDimensions(total_rows, total_cols);
216
217 if (total_rows == 0 || total_cols == 0) {
218 return false;
219 }
220
221 int local_rows = 0;
222 int start_row = 0;
223 int end_row = 0;
224 CalculateLocalRows(rank, size, total_rows, local_rows, start_row, end_row);
225
226 if (rank == 0) {
227 SendDataToWorkers(size, total_rows, total_cols);
228 }
229
230 std::vector<InType> local_data;
231 ProcessLocalData(rank, local_rows, total_cols, start_row, local_data);
232
233 std::vector<InType> local_max_values(local_rows);
234 FindLocalMaxValues(local_rows, total_cols, local_data, local_max_values);
235
236 GatherResults(rank, size, total_rows, local_max_values, start_row, local_rows);
237
238 return true;
239 }
240
241 } // namespace yakimov_i_max_values_in_matrix_rows
242