GCC Code Coverage Report


Directory: ./
File: tasks/shvetsova_k_max_diff_neig_vec/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 85 85 100.0%
Functions: 9 9 100.0%
Branches: 53 82 64.6%

Line Branch Exec Source
1 #include "shvetsova_k_max_diff_neig_vec/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cmath>
8 #include <cstddef>
9 #include <utility>
10 #include <vector>
11
12 #include "shvetsova_k_max_diff_neig_vec/common/include/common.hpp"
13
14 namespace shvetsova_k_max_diff_neig_vec {
15
16
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ShvetsovaKMaxDiffNeigVecMPI::ShvetsovaKMaxDiffNeigVecMPI(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput() = in;
19 GetOutput() = std::pair<double, double>{0.0, 0.0};
20 20 }
21
22 20 bool ShvetsovaKMaxDiffNeigVecMPI::ValidationImpl() {
23 20 return true;
24 }
25
26 20 bool ShvetsovaKMaxDiffNeigVecMPI::PreProcessingImpl() {
27 20 data_ = GetInput();
28 20 return true;
29 }
30
31 20 bool ShvetsovaKMaxDiffNeigVecMPI::RunImpl() {
32 20 int count_of_proc = 0;
33 20 int rank = 0;
34
35 20 MPI_Comm_size(MPI_COMM_WORLD, &count_of_proc);
36 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
37
38 int size_of_vector = 0;
39 20 size_of_vector = static_cast<int>(data_.size());
40
41 20 MPI_Bcast(&size_of_vector, 1, MPI_INT, 0, MPI_COMM_WORLD); // сказали всем процессам, какой размер у вектора
42
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 if (size_of_vector < 2) {
43 GetOutput() = {0.0, 0.0};
44 4 return true;
45 }
46 16 std::vector<int> count_elems(count_of_proc, 0); // количсетво элементов на каждый из процессов
47
1/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
16 std::vector<int> ind(count_of_proc, 0); // индекс, начиная с которого элементы принадлежат процессам
48
49
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 CreateDistribution(count_of_proc, size_of_vector, count_elems, ind, rank);
50
51
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 int part_size = count_elems[rank];
52
1/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
16 std::vector<double> part(part_size);
53
54
4/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
40 MPI_Scatterv(rank == 0 ? data_.data() : nullptr, count_elems.data(), ind.data(), MPI_DOUBLE,
55 part_size > 0 ? part.data() : nullptr, part_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
56
57 // Вычисляем максимальную разницу внутри локальной части
58 16 double local_diff = -1.0;
59 16 double local_a = 0.0;
60 16 double local_b = 0.0;
61
62
2/2
✓ Branch 0 taken 25739 times.
✓ Branch 1 taken 16 times.
25755 for (int i = 0; i + 1 < part_size; ++i) {
63
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 25655 times.
25739 double diff = std::abs(part[i] - part[i + 1]);
64
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 25655 times.
25739 if (diff > local_diff) {
65 84 local_diff = diff;
66 84 local_a = part[i];
67 84 local_b = part[i + 1];
68 }
69 }
70
71
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ProcessBoundaries(count_of_proc, rank, part, part_size, local_diff, local_a, local_b);
72
73 // Находим глобальный максимум
74
1/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
16 std::vector<double> all_diffs(count_of_proc);
75
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
24 MPI_Gather(&local_diff, 1, MPI_DOUBLE, rank == 0 ? all_diffs.data() : nullptr, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
76
77
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 int winner_rank = WinnerRank(all_diffs, count_of_proc, rank);
78
79 16 std::array<double, 2> result_pair{};
80
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 CollectGlobalPair(winner_rank, local_a, local_b, result_pair, count_of_proc);
81
82
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Bcast(result_pair.data(), 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
83
84 GetOutput() = {result_pair[0], result_pair[1]};
85 return true;
86 }
87
88 // Реализация функций
89 16 void ShvetsovaKMaxDiffNeigVecMPI::CreateDistribution(int count_of_proc, int size_of_vector,
90 std::vector<int> &count_elems, std::vector<int> &ind, int rank) {
91
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank == 0) {
92 8 int base = size_of_vector / count_of_proc;
93 8 int rem = size_of_vector % count_of_proc;
94 int sum = 0;
95
96
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (int i = 0; i < count_of_proc; i++) {
97
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
31 count_elems[i] = base + (i < rem ? 1 : 0);
98 16 ind[i] = sum;
99 16 sum += count_elems[i];
100 }
101 }
102
103 16 MPI_Bcast(count_elems.data(), count_of_proc, MPI_INT, 0, MPI_COMM_WORLD);
104 16 MPI_Bcast(ind.data(), count_of_proc, MPI_INT, 0, MPI_COMM_WORLD);
105 16 }
106
107 16 int ShvetsovaKMaxDiffNeigVecMPI::WinnerRank(const std::vector<double> &all_diffs, int count_of_proc, int rank) {
108 16 int winner_rank = 0;
109
110
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank == 0) {
111 8 double global_diff = *std::ranges::max_element(all_diffs);
112
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 for (int i = 0; i < count_of_proc; i++) {
113
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (std::abs(all_diffs[i] - global_diff) < 1e-12) {
114 8 winner_rank = i;
115 8 break;
116 }
117 }
118 } else {
119 winner_rank = 0;
120 }
121
122 16 MPI_Bcast(&winner_rank, 1, MPI_INT, 0, MPI_COMM_WORLD);
123 16 return winner_rank;
124 }
125
126 16 void ShvetsovaKMaxDiffNeigVecMPI::CollectGlobalPair(int winner_rank, double local_a, double local_b,
127 std::array<double, 2> &result_pair, int count_of_proc) {
128 16 std::array<double, 2> local_pair = {local_a, local_b};
129
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 std::vector<double> all_pairs(static_cast<size_t>(count_of_proc) * 2);
130
131
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Gather(local_pair.data(), 2, MPI_DOUBLE, all_pairs.data(), 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
132
133
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Bcast(&winner_rank, 1, MPI_INT, 0, MPI_COMM_WORLD);
134
135
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 result_pair[0] = all_pairs[static_cast<size_t>(winner_rank) * 2];
136
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 result_pair[1] = all_pairs[(static_cast<size_t>(winner_rank) * 2) + 1];
137 16 }
138 16 void ShvetsovaKMaxDiffNeigVecMPI::ProcessBoundaries(int count_of_proc, int rank, const std::vector<double> &part,
139 int part_size, double &local_diff, double &local_a,
140 double &local_b) {
141
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (count_of_proc > 1) {
142
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 double send_val = (part_size > 0) ? part[part_size - 1] : 0.0;
143 16 double recv_val = 0.0;
144
145 // Отправляем последний элемент следующему процессу
146
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank < count_of_proc - 1) {
147 8 MPI_Send(&send_val, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD);
148 }
149
150 // Получаем последний элемент от предыдущего процесса
151
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (rank > 0) {
152 8 MPI_Recv(&recv_val, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
153
154 // Проверяем разницу на границе
155
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (part_size > 0) {
156
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 double diff = std::abs(recv_val - part[0]);
157
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (diff > local_diff) {
158 1 local_diff = diff;
159 1 local_a = recv_val;
160 1 local_b = part[0];
161 }
162 }
163 }
164 }
165 16 }
166
167 20 bool ShvetsovaKMaxDiffNeigVecMPI::PostProcessingImpl() {
168 20 return true;
169 }
170
171 } // namespace shvetsova_k_max_diff_neig_vec
172