GCC Code Coverage Report


Directory: ./
File: tasks/shekhirev_v_cg_method/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 78 80 97.5%
Functions: 6 7 85.7%
Branches: 48 88 54.5%

Line Branch Exec Source
1 #include "../include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <vector>
8
9 #include "../../common/include/common.hpp"
10
11 namespace shekhirev_v_cg_method_mpi {
12
13
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 ConjugateGradientMPI::ConjugateGradientMPI(const shekhirev_v_cg_method::InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 6 }
17
18 6 bool ConjugateGradientMPI::ValidationImpl() {
19 6 int rank = 0;
20 6 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
21
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rank == 0) {
22 3 const int n = GetInput().n;
23
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 return n > 0 && GetInput().A.size() == static_cast<size_t>(n) * n && GetInput().b.size() == static_cast<size_t>(n);
24 }
25 return true;
26 }
27
28 6 bool ConjugateGradientMPI::PreProcessingImpl() {
29 6 return true;
30 }
31
32 12 std::vector<double> ConjugateGradientMPI::LocalMultiply(const std::vector<double> &local_a,
33 const std::vector<double> &global_p, int local_n, int n) {
34 12 std::vector<double> res(local_n, 0.0);
35
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 12 times.
27 for (int i = 0; i < local_n; ++i) {
36
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 15 times.
54 for (int j = 0; j < n; ++j) {
37 39 size_t index = (static_cast<size_t>(i) * n) + j;
38 39 res[i] += local_a[index] * global_p[j];
39 }
40 }
41 12 return res;
42 }
43
44 double ConjugateGradientMPI::LocalDotProduct(const std::vector<double> &a, const std::vector<double> &b) {
45 double res = 0.0;
46
4/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
40 for (size_t i = 0; i < a.size(); ++i) {
47 22 res += (a[i] * b[i]);
48 }
49 return res;
50 }
51
52 6 bool ConjugateGradientMPI::RunImpl() {
53 6 int rank = 0;
54 6 int size = 0;
55 6 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
56 6 MPI_Comm_size(MPI_COMM_WORLD, &size);
57
58 6 int n = 0;
59
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rank == 0) {
60 3 n = GetInput().n;
61 }
62 6 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
63
64 6 const int count_per_proc = n / size;
65 6 const int remainder = n % size;
66
67 6 std::vector<int> counts(size);
68
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displs(size);
69
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> matrix_counts(size);
70
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> matrix_displs(size);
71
72 int offset = 0;
73
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < size; ++i) {
74
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
22 counts[i] = count_per_proc + (i < remainder ? 1 : 0);
75 12 displs[i] = offset;
76 12 matrix_counts[i] = counts[i] * n;
77 12 matrix_displs[i] = offset * n;
78 12 offset += counts[i];
79 }
80
81
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 const int local_n = counts[rank];
82
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_a(static_cast<size_t>(local_n) * n);
83
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_b(local_n);
84
85 const auto &input_a = GetInput().A;
86 const auto &input_bb = GetInput().b;
87
88
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Scatterv(input_a.data(), matrix_counts.data(), matrix_displs.data(), MPI_DOUBLE, local_a.data(), local_n * n,
89 MPI_DOUBLE, 0, MPI_COMM_WORLD);
90
91
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Scatterv(input_bb.data(), counts.data(), displs.data(), MPI_DOUBLE, local_b.data(), local_n, MPI_DOUBLE, 0,
92 MPI_COMM_WORLD);
93
94
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_x(local_n, 0.0);
95
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 std::vector<double> local_r = local_b;
96
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 std::vector<double> local_p = local_r;
97
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> global_p(n);
98
99 6 double local_rs_old = LocalDotProduct(local_r, local_r);
100 6 double global_rs_old = 0.0;
101
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Allreduce(&local_rs_old, &global_rs_old, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
102
103 6 const int max_iter = n * 2;
104 const double epsilon = 1e-10;
105
106
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int k = 0; k < max_iter; ++k) {
107
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allgatherv(local_p.data(), local_n, MPI_DOUBLE, global_p.data(), counts.data(), displs.data(), MPI_DOUBLE,
108 MPI_COMM_WORLD);
109
110
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<double> local_ap = LocalMultiply(local_a, global_p, local_n, n);
111 12 double local_p_ap = LocalDotProduct(local_p, local_ap);
112
113 12 double global_p_ap = 0.0;
114
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allreduce(&local_p_ap, &global_p_ap, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
115
116 12 const double alpha = global_rs_old / global_p_ap;
117
118 12 double local_rs_new = 0.0;
119
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 12 times.
27 for (int i = 0; i < local_n; ++i) {
120 15 local_x[i] += (alpha * local_p[i]);
121 15 local_r[i] -= (alpha * local_ap[i]);
122 15 local_rs_new += (local_r[i] * local_r[i]);
123 }
124
125 12 double global_rs_new = 0.0;
126
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allreduce(&local_rs_new, &global_rs_new, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
127
128
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (std::sqrt(global_rs_new) < epsilon) {
129 break;
130 }
131
132 6 const double beta = global_rs_new / global_rs_old;
133 6 global_rs_old = global_rs_new;
134
135
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 for (int i = 0; i < local_n; ++i) {
136 8 local_p[i] = local_r[i] + (beta * local_p[i]);
137 }
138 }
139
140
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rank == 0) {
141
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 GetOutput().resize(n);
142 }
143
144
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Gatherv(local_x.data(), local_n, MPI_DOUBLE, GetOutput().data(), counts.data(), displs.data(), MPI_DOUBLE, 0,
145 MPI_COMM_WORLD);
146
147 6 return true;
148 }
149
150 6 bool ConjugateGradientMPI::PostProcessingImpl() {
151 6 return true;
152 }
153
154 } // namespace shekhirev_v_cg_method_mpi
155