GCC Code Coverage Report


Directory: ./
File: tasks/smyshlaev_a_sle_cg_seq/tbb/src/ops_tbb.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 57 116 49.1%
Functions: 8 14 57.1%
Branches: 34 112 30.4%

Line Branch Exec Source
1 #include "smyshlaev_a_sle_cg_seq/tbb/include/ops_tbb.hpp" // Изменено на tbb
2
3 #include <tbb/tbb.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <functional>
8 #include <vector>
9
10 #include "oneapi/tbb/parallel_for.h"
11 #include "smyshlaev_a_sle_cg_seq/common/include/common.hpp"
12 #include "util/include/util.hpp"
13
14 namespace smyshlaev_a_sle_cg_seq {
15
16 namespace {
17
18 double ComputeDotProductTbb(const std::vector<double> &v1, const std::vector<double> &v2) {
19 int n = static_cast<int>(v1.size());
20 return tbb::parallel_reduce(tbb::blocked_range<int>(0, n), 0.0,
21 [&](const tbb::blocked_range<int> &range, double init) -> double {
22 for (int i = range.begin(); i != range.end(); ++i) {
23 init += v1[i] * v2[i];
24 }
25 return init;
26 }, std::plus<>());
27 }
28
29 void ComputeApTbb(const std::vector<double> &matrix, const std::vector<double> &p, std::vector<double> &ap, int n) {
30 tbb::parallel_for(tbb::blocked_range<int>(0, n), [&](const tbb::blocked_range<int> &range) {
31 for (int i = range.begin(); i != range.end(); ++i) {
32 double sum = 0.0;
33 for (int j = 0; j < n; ++j) {
34 sum += matrix[(i * n) + j] * p[j];
35 }
36 ap[i] = sum;
37 }
38 });
39 }
40
41 double UpdateResultAndResidualTbb(std::vector<double> &result, std::vector<double> &r, const std::vector<double> &p,
42 const std::vector<double> &ap, double alpha) {
43 int n = static_cast<int>(result.size());
44 return tbb::parallel_reduce(tbb::blocked_range<int>(0, n), 0.0,
45 [&](const tbb::blocked_range<int> &range, double init) -> double {
46 for (int i = range.begin(); i != range.end(); ++i) {
47 result[i] += alpha * p[i];
48 r[i] -= alpha * ap[i];
49 init += r[i] * r[i];
50 }
51 return init;
52 }, std::plus<>());
53 }
54
55 void UpdatePTbb(std::vector<double> &p, const std::vector<double> &r, double beta) {
56 int n = static_cast<int>(p.size());
57 tbb::parallel_for(tbb::blocked_range<int>(0, n), [&](const tbb::blocked_range<int> &range) {
58 for (int i = range.begin(); i != range.end(); ++i) {
59 p[i] = r[i] + (beta * p[i]);
60 }
61 });
62 }
63
64 double ComputeDotProduct(const std::vector<double> &v1, const std::vector<double> &v2) {
65 double result = 0.0;
66 96 int n = static_cast<int>(v1.size());
67
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 96 times.
348 for (int i = 0; i < n; ++i) {
68 252 result += v1[i] * v2[i];
69 }
70 return result;
71 }
72
73 96 void ComputeAp(const std::vector<double> &matrix, const std::vector<double> &p, std::vector<double> &ap, int n) {
74
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 96 times.
348 for (int i = 0; i < n; ++i) {
75 double sum = 0.0;
76
2/2
✓ Branch 0 taken 708 times.
✓ Branch 1 taken 252 times.
960 for (int j = 0; j < n; ++j) {
77 708 sum += matrix[(i * n) + j] * p[j];
78 }
79 252 ap[i] = sum;
80 }
81 96 }
82
83 96 double UpdateResultAndResidual(std::vector<double> &result, std::vector<double> &r, const std::vector<double> &p,
84 const std::vector<double> &ap, double alpha) {
85 double rs_new = 0.0;
86 96 int n = static_cast<int>(result.size());
87
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 96 times.
348 for (int i = 0; i < n; ++i) {
88 252 result[i] += alpha * p[i];
89 252 r[i] -= alpha * ap[i];
90 252 rs_new += r[i] * r[i];
91 }
92 96 return rs_new;
93 }
94
95 void UpdateP(std::vector<double> &p, const std::vector<double> &r, double beta) {
96 int n = static_cast<int>(p.size());
97
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 for (int i = 0; i < n; ++i) {
98 120 p[i] = r[i] + (beta * p[i]);
99 }
100 }
101
102 } // namespace
103
104
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 SmyshlaevASleCgTaskTBB::SmyshlaevASleCgTaskTBB(const InType &in) {
105 SetTypeOfTask(GetStaticTypeOfTask());
106 GetInput() = in;
107 48 }
108
109
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool SmyshlaevASleCgTaskTBB::ValidationImpl() {
110 const auto &a = GetInput().A;
111 const auto &b = GetInput().b;
112
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 if (a.empty() || b.empty()) {
113 return false;
114 }
115
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (a.size() != b.size()) {
116 return false;
117 }
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (a.size() != a[0].size()) {
119 return false;
120 }
121 return true;
122 }
123
124 48 bool SmyshlaevASleCgTaskTBB::PreProcessingImpl() {
125 const auto &a = GetInput().A;
126 size_t n = a.size();
127 48 flat_A_.resize(n * n);
128
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 48 times.
180 for (size_t i = 0; i < n; ++i) {
129
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 132 times.
528 for (size_t j = 0; j < n; ++j) {
130 396 flat_A_[(i * n) + j] = a[i][j];
131 }
132 }
133 48 return true;
134 }
135
136 48 bool SmyshlaevASleCgTaskTBB::RunSequential() {
137 48 const auto &b = GetInput().b;
138 48 int n = static_cast<int>(b.size());
139 48 std::vector<double> r = b;
140
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 std::vector<double> p = r;
141
1/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
48 std::vector<double> ap(n, 0.0);
142
1/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
48 std::vector<double> result(n, 0.0);
143
144 double rs_old = 0.0;
145
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 48 times.
180 for (int i = 0; i < n; ++i) {
146 132 rs_old += r[i] * r[i];
147 }
148
149 const double epsilon = 1e-9;
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (std::sqrt(rs_old) < epsilon) {
151 GetOutput() = result;
152 return true;
153 }
154
155 48 const int max_iterations = n * 2;
156
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 for (int iter = 0; iter < max_iterations; ++iter) {
157 96 ComputeAp(flat_A_, p, ap, n);
158 double p_ap = ComputeDotProduct(p, ap);
159
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (std::abs(p_ap) < 1e-15) {
160 break;
161 }
162
163 96 double alpha = rs_old / p_ap;
164 96 double rs_new = UpdateResultAndResidual(result, r, p, ap, alpha);
165
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 48 times.
96 if (std::sqrt(rs_new) < epsilon) {
166 break;
167 }
168
169 48 double beta = rs_new / rs_old;
170 UpdateP(p, r, beta);
171 rs_old = rs_new;
172 }
173
174
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 GetOutput() = result;
175 return true;
176 }
177
178 bool SmyshlaevASleCgTaskTBB::RunParallel(int num_threads) {
179 tbb::global_control thread_limit(tbb::global_control::max_allowed_parallelism, num_threads);
180
181 const auto &b = GetInput().b;
182 int n = static_cast<int>(b.size());
183 std::vector<double> r = b;
184 std::vector<double> p = r;
185 std::vector<double> ap(n, 0.0);
186 std::vector<double> result(n, 0.0);
187
188 double rs_old = tbb::parallel_reduce(tbb::blocked_range<int>(0, n), 0.0,
189 [&](const tbb::blocked_range<int> &range, double init) -> double {
190 for (int i = range.begin(); i != range.end(); ++i) {
191 init += r[i] * r[i];
192 }
193 return init;
194 }, std::plus<>());
195
196 const double epsilon = 1e-9;
197 if (std::sqrt(rs_old) < epsilon) {
198 GetOutput() = result;
199 return true;
200 }
201
202 const int max_iterations = n * 2;
203 for (int iter = 0; iter < max_iterations; ++iter) {
204 ComputeApTbb(flat_A_, p, ap, n);
205 double p_ap = ComputeDotProductTbb(p, ap);
206 if (std::abs(p_ap) < 1e-15) {
207 break;
208 }
209
210 double alpha = rs_old / p_ap;
211 double rs_new = UpdateResultAndResidualTbb(result, r, p, ap, alpha);
212 if (std::sqrt(rs_new) < epsilon) {
213 break;
214 }
215
216 double beta = rs_new / rs_old;
217 UpdatePTbb(p, r, beta);
218 rs_old = rs_new;
219 }
220
221 GetOutput() = result;
222 return true;
223 }
224
225
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool SmyshlaevASleCgTaskTBB::RunImpl() {
226 const auto &b = GetInput().b;
227
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (b.empty()) {
228 return true;
229 }
230 48 int n = static_cast<int>(b.size());
231
232 48 int num_threads = ppc::util::GetNumThreads();
233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (n < num_threads * 100) {
234 num_threads = 1;
235 }
236 if (num_threads == 1) {
237 48 return RunSequential();
238 }
239
240 return RunParallel(num_threads);
241 }
242
243 48 bool SmyshlaevASleCgTaskTBB::PostProcessingImpl() {
244 48 return true;
245 }
246
247 } // namespace smyshlaev_a_sle_cg_seq
248