GCC Code Coverage Report


Directory: ./
File: tasks/kruglova_a_conjugate_gradient_sle/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 63 64 98.4%
Functions: 7 7 100.0%
Branches: 26 56 46.4%

Line Branch Exec Source
1 #include "kruglova_a_conjugate_gradient_sle/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <cmath>
7 #include <cstddef>
8 #include <vector>
9
10 #include "kruglova_a_conjugate_gradient_sle/common/include/common.hpp"
11
12 namespace kruglova_a_conjugate_gradient_sle {
13
14 namespace {
15
16 void CalculateDistribution(int n, int mpi_size, int rank, int &local_n, int &offset) {
17 36 int q = n / mpi_size;
18 36 int rem = n % mpi_size;
19
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
24 if (rank < rem) {
20 12 local_n = q + 1;
21 12 offset = rank * (q + 1);
22 } else {
23 8 local_n = q;
24 24 offset = (rank * q) + rem;
25 }
26 }
27
28 void ComputeLocalMatVec(int local_n, int n, int offset, const InType &input, const std::vector<double> &p_full,
29 std::vector<double> &local_ap) {
30 66 #pragma omp parallel for default(none) shared(local_n, n, offset, input, p_full, local_ap)
31 for (int i = 0; i < local_n; ++i) {
32 double sum = 0.0;
33 size_t row_idx = (static_cast<size_t>(offset) + i) * static_cast<size_t>(n);
34 for (int j = 0; j < n; ++j) {
35 sum += input.A[row_idx + static_cast<size_t>(j)] * p_full[j];
36 }
37 local_ap[i] = sum;
38 }
39 }
40
41 78 double GlobalDot(int local_n, const std::vector<double> &v1, const std::vector<double> &v2) {
42 78 double local_sum = 0.0;
43 78 #pragma omp parallel for default(none) shared(local_n, v1, v2) reduction(+ : local_sum)
44 for (int i = 0; i < local_n; ++i) {
45 local_sum += v1[i] * v2[i];
46 }
47 78 double global_sum = 0.0;
48 78 MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
49 78 return global_sum;
50 }
51
52 66 double UpdateLocalXR(int local_n, double alpha, const std::vector<double> &local_p, const std::vector<double> &local_ap,
53 std::vector<double> &local_x, std::vector<double> &local_r) {
54 66 double local_rsnew = 0.0;
55 66 #pragma omp parallel for default(none) shared(local_n, alpha, local_p, local_ap, local_x, local_r) \
56 reduction(+ : local_rsnew)
57 for (int i = 0; i < local_n; ++i) {
58 local_x[i] += alpha * local_p[i];
59 local_r[i] -= alpha * local_ap[i];
60 local_rsnew += local_r[i] * local_r[i];
61 }
62 66 double global_rsnew = 0.0;
63 66 MPI_Allreduce(&local_rsnew, &global_rsnew, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
64 66 return global_rsnew;
65 }
66
67 } // namespace
68
69
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 KruglovaAConjGradSleALL::KruglovaAConjGradSleALL(const InType &in) {
70 SetTypeOfTask(GetStaticTypeOfTask());
71 GetInput() = in;
72 12 }
73
74 12 bool KruglovaAConjGradSleALL::ValidationImpl() {
75 const auto &in = GetInput();
76
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (in.size <= 0) {
77 return false;
78 }
79
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 auto sz = static_cast<size_t>(in.size);
80
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (in.A.size() != sz * sz) {
81 return false;
82 }
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (in.b.size() != sz) {
84 return false;
85 }
86 return true;
87 }
88
89 12 bool KruglovaAConjGradSleALL::PreProcessingImpl() {
90 12 GetOutput().assign(GetInput().size, 0.0);
91 12 return true;
92 }
93
94 12 bool KruglovaAConjGradSleALL::RunImpl() {
95 12 int rank = 0;
96 12 int mpi_size = 0;
97 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
98 12 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
99
100 const auto &input = GetInput();
101 12 const int n = input.size;
102 auto &x_global = GetOutput();
103
104 int local_n = 0;
105 12 int offset = 0;
106
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 CalculateDistribution(n, mpi_size, rank, local_n, offset);
107
108 12 std::vector<double> local_r(local_n);
109
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<double> local_p(local_n);
110
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<double> local_ap(local_n);
111
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<double> local_x(local_n, 0.0);
112
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<double> p_full(n);
113
114
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> counts(mpi_size);
115
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> displs(mpi_size);
116
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int i = 0; i < mpi_size; ++i) {
117 int ln = 0;
118 int off = 0;
119 CalculateDistribution(n, mpi_size, i, ln, off);
120 24 counts[i] = ln;
121 24 displs[i] = off;
122 }
123
124 12 #pragma omp parallel for default(none) shared(local_n, offset, local_r, local_p, input)
125 for (int i = 0; i < local_n; ++i) {
126 local_r[i] = input.b[static_cast<size_t>(offset) + i];
127 local_p[i] = local_r[i];
128 }
129
130
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 double rsold = GlobalDot(local_n, local_r, local_r);
131 const double tolerance = 1e-8;
132
133
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 for (int iter = 0; iter < n; ++iter) {
134
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 MPI_Allgatherv(local_p.data(), local_n, MPI_DOUBLE, p_full.data(), counts.data(), displs.data(), MPI_DOUBLE,
135 MPI_COMM_WORLD);
136
137 66 ComputeLocalMatVec(local_n, n, offset, input, p_full, local_ap);
138
139
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 double p_ap = GlobalDot(local_n, local_p, local_ap);
140
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (std::abs(p_ap) < 1e-16) {
141 break;
142 }
143
144
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 double rsnew = UpdateLocalXR(local_n, rsold / p_ap, local_p, local_ap, local_x, local_r);
145
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 12 times.
66 if (std::sqrt(rsnew) < tolerance) {
146 break;
147 }
148
149 54 double beta = rsnew / rsold;
150 54 #pragma omp parallel for default(none) shared(local_n, local_p, local_r, beta)
151 for (int i = 0; i < local_n; ++i) {
152 local_p[i] = local_r[i] + (beta * local_p[i]);
153 }
154 rsold = rsnew;
155 }
156
157
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allgatherv(local_x.data(), local_n, MPI_DOUBLE, x_global.data(), counts.data(), displs.data(), MPI_DOUBLE,
158 MPI_COMM_WORLD);
159 12 return true;
160 }
161
162 12 bool KruglovaAConjGradSleALL::PostProcessingImpl() {
163 12 return true;
164 }
165
166 } // namespace kruglova_a_conjugate_gradient_sle
167