GCC Code Coverage Report


Directory: ./
File: tasks/kutergin_v_reduce/mpi/src/reduce_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 44 44 100.0%
Functions: 6 6 100.0%
Branches: 23 28 82.1%

Line Branch Exec Source
1 #include "../include/reduce_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstdint>
6 #include <cstring>
7 #include <numeric>
8
9 #include "../../common/include/common.hpp"
10
11 namespace kutergin_v_reduce {
12
13 namespace {
14
15 // вспомогательная функция для применения операции op к двум буферам a и b
16 void ApplyOp(void *a, const void *b, int count, MPI_Datatype datatype, MPI_Op op) {
17
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (op == MPI_SUM && datatype == MPI_INT) {
18
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < count; ++i) {
19 2 reinterpret_cast<int *>(a)[i] += reinterpret_cast<const int *>(b)[i];
20 }
21 }
22 }
23
24 } // namespace
25
26
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 ReduceMPI::ReduceMPI(const InType &in) {
27 SetTypeOfTask(GetStaticTypeOfTask()); // установка типа задачи
28 GetInput() = in; // сохранение входных данных
29 8 GetOutput() = 0; // инициализация выходных данных
30 8 }
31
32 8 int Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) {
33 8 int process_rank = 0;
34 8 int process_count = 0;
35 8 MPI_Comm_rank(comm, &process_rank);
36 8 MPI_Comm_size(comm, &process_count);
37
38
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
8 if (root < 0 || root >= process_count) // root-процесс не существует
39 {
40 return MPI_ERR_ROOT; // возвращение стандартного кода ошибки MPI
41 }
42
43 4 int type_size = 0;
44 4 MPI_Type_size(datatype, &type_size);
45
46 // Древовидный сбор
47
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int mask = 1; mask < process_count;
48 2 mask <<= 1) // удвоение битовой маски на каждой итерации посредством битового сдвига
49 {
50
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if ((process_rank & mask) != 0) // процессы-отправители
51 {
52 2 MPI_Send(sendbuf, count, datatype, process_rank - mask, 0, comm);
53 break;
54 }
55
56
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (process_rank + mask < process_count) // процессы-получатели
57 {
58 2 auto *recv_temp = new uint8_t[static_cast<size_t>(count) * type_size];
59 2 MPI_Recv(recv_temp, count, datatype, process_rank + mask, 0, comm, MPI_STATUS_IGNORE);
60
61 ApplyOp(sendbuf, recv_temp, count, datatype, op); // выполнение op (MPI_SUM) для datatype (MPI_INT)
62
63 2 delete[] recv_temp;
64 }
65 }
66
67 // Результат с процесса 0 отправляется на процесс 'root'
68
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
4 if (process_rank == 0 && root != 0) {
69 1 MPI_Send(sendbuf, count, datatype, root, 0, comm);
70 }
71
72 // Корневой процесс 'root' получает финальный результат
73
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (process_rank == root) {
74
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (root == 0) {
75 1 std::memcpy(recvbuf, sendbuf, static_cast<size_t>(count) * type_size);
76 } else {
77 1 MPI_Recv(recvbuf, count, datatype, 0, 0, comm, MPI_STATUS_IGNORE);
78 }
79 }
80
81 return MPI_SUCCESS;
82 }
83
84 8 bool ReduceMPI::ValidationImpl() {
85 8 return true;
86 }
87
88 8 bool ReduceMPI::PreProcessingImpl() {
89 8 return true;
90 }
91
92 8 bool ReduceMPI::RunImpl() {
93 8 int rank = 0;
94 8 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
95
96 const auto &input = GetInput();
97 8 int root_process = input.root;
98 const auto &input_vec = input.data;
99
100 /*
101 int send_data = input_vec.empty() ? 0 : input_vec[0]; // у каждого процесса - свое число
102 int recv_data = 0; // буфер для результат
103 */
104
105 int local_sum =
106 8 std::accumulate(input_vec.begin(), input_vec.end(), 0); // вычисление локальной суммы всего входного вектора
107 8 int global_sum = 0;
108
109 // Вызов своей реализации Reduce()
110 8 Reduce(&local_sum, &global_sum, 1, MPI_INT, MPI_SUM, root_process, MPI_COMM_WORLD);
111
112 // Только корневой процесс записывает результат в Output
113
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (rank == root_process) {
114 2 GetOutput() = global_sum;
115 }
116
117 8 return true;
118 }
119
120 8 bool ReduceMPI::PostProcessingImpl() {
121 8 return true;
122 }
123
124 } // namespace kutergin_v_reduce
125