GCC Code Coverage Report


Directory: ./
File: tasks/zagryadskov_m_complex_spmm_ccs/tbb/src/ops_tbb.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 74 74 100.0%
Functions: 11 11 100.0%
Branches: 39 48 81.2%

Line Branch Exec Source
1 #include "zagryadskov_m_complex_spmm_ccs/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/blocked_range.h>
4 #include <tbb/enumerable_thread_specific.h>
5 #include <tbb/tbb.h>
6
7 #include <complex>
8 #include <vector>
9
10 #include "tbb/parallel_for.h"
11 #include "zagryadskov_m_complex_spmm_ccs/common/include/common.hpp"
12
13 namespace zagryadskov_m_complex_spmm_ccs {
14
15
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 ZagryadskovMComplexSpMMCCSTBB::ZagryadskovMComplexSpMMCCSTBB(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GetOutput() = CCS();
19 12 }
20
21 12 void ZagryadskovMComplexSpMMCCSTBB::SpMMSymbolic(const CCS &a, const CCS &b, std::vector<int> &col_ptr) {
22 12 const int m = a.m;
23 12 const int n = b.n;
24
25 12 std::vector<int> col_counts(n, 0);
26
27
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 tbb::enumerable_thread_specific<std::vector<int>> tls_marker([&]() { return std::vector<int>(m, -1); });
28
29
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tbb::parallel_for(tbb::blocked_range<int>(0, n, 64), [&](const tbb::blocked_range<int> &r) {
30 12 auto &marker = tls_marker.local();
31
32
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 12 times.
40 for (int j = r.begin(); j < r.end(); ++j) {
33 int count = 0;
34
35
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 28 times.
68 for (int k = b.col_ptr[j]; k < b.col_ptr[j + 1]; ++k) {
36 40 int b_row = b.row_ind[k];
37
38
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 40 times.
84 for (int zp = a.col_ptr[b_row]; zp < a.col_ptr[b_row + 1]; ++zp) {
39
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 int a_row = a.row_ind[zp];
40
41
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 if (marker[a_row] != j) {
42 36 marker[a_row] = j;
43 36 ++count;
44 }
45 }
46 }
47
48 28 col_counts[j] = count;
49 }
50 12 });
51
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 col_ptr.resize(n + 1);
52 12 col_ptr[0] = 0;
53
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 12 times.
40 for (int j = 0; j < n; ++j) {
54 28 col_ptr[j + 1] = col_ptr[j] + col_counts[j];
55 }
56 24 }
57
58
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12 times.
28 void ZagryadskovMComplexSpMMCCSTBB::SpMMKernel(const CCS &a, const CCS &b, CCS &c, const std::complex<double> &zero,
59 double eps, std::vector<int> &rows,
60 std::vector<std::complex<double>> &acc, std::vector<int> &marker,
61 int j) {
62 rows.clear();
63
64 28 int write_ptr = c.col_ptr[j];
65
66
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 28 times.
68 for (int k = b.col_ptr[j]; k < b.col_ptr[j + 1]; ++k) {
67 40 std::complex<double> tmpval = b.values[k];
68 40 int b_row = b.row_ind[k];
69
70
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 40 times.
84 for (int zp = a.col_ptr[b_row]; zp < a.col_ptr[b_row + 1]; ++zp) {
71
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 int a_row = a.row_ind[zp];
72
73
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 acc[a_row] += tmpval * a.values[zp];
74
75
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 if (marker[a_row] != j) {
76
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 16 times.
36 marker[a_row] = j;
77 rows.push_back(a_row);
78 }
79 }
80 }
81
82
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 28 times.
64 for (int r_idx : rows) {
83
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (std::norm(acc[r_idx]) > eps * eps) {
84 36 c.row_ind[write_ptr] = r_idx;
85 36 c.values[write_ptr] = acc[r_idx];
86 36 ++write_ptr;
87 }
88 36 acc[r_idx] = zero;
89 }
90 28 }
91
92 12 void ZagryadskovMComplexSpMMCCSTBB::SpMMNumeric(const CCS &a, const CCS &b, CCS &c, const std::complex<double> &zero,
93 double eps) {
94 12 const int m = a.m;
95 12 const int n = b.n;
96
97 24 tbb::enumerable_thread_specific<std::vector<int>> tls_marker([&]() { return std::vector<int>(m, -1); });
98
99 tbb::enumerable_thread_specific<std::vector<std::complex<double>>> tls_acc(
100
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 [&]() { return std::vector<std::complex<double>>(m, zero); });
101
102
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tbb::parallel_for(tbb::blocked_range<int>(0, n, 64), [&](const tbb::blocked_range<int> &r) {
103 12 auto &marker = tls_marker.local();
104 12 auto &acc = tls_acc.local();
105
106 12 std::vector<int> rows;
107
108
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 12 times.
40 for (int j = r.begin(); j < r.end(); ++j) {
109
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 SpMMKernel(a, b, c, zero, eps, rows, acc, marker, j);
110 }
111 12 });
112 12 }
113
114 12 void ZagryadskovMComplexSpMMCCSTBB::SpMM(const CCS &a, const CCS &b, CCS &c) {
115 12 c.m = a.m;
116 12 c.n = b.n;
117
118 12 std::complex<double> zero(0.0, 0.0);
119 const double eps = 1e-14;
120
121 12 SpMMSymbolic(a, b, c.col_ptr);
122
123 12 int nnz = c.col_ptr[b.n];
124 12 c.row_ind.resize(nnz);
125 12 c.values.resize(nnz);
126
127 12 SpMMNumeric(a, b, c, zero, eps);
128 12 }
129
130 12 bool ZagryadskovMComplexSpMMCCSTBB::ValidationImpl() {
131 const CCS &a = std::get<0>(GetInput());
132 const CCS &b = std::get<1>(GetInput());
133 12 return a.n == b.m;
134 }
135
136 12 bool ZagryadskovMComplexSpMMCCSTBB::PreProcessingImpl() {
137 12 return true;
138 }
139
140 12 bool ZagryadskovMComplexSpMMCCSTBB::RunImpl() {
141 const CCS &a = std::get<0>(GetInput());
142 const CCS &b = std::get<1>(GetInput());
143 CCS &c = GetOutput();
144
145 12 ZagryadskovMComplexSpMMCCSTBB::SpMM(a, b, c);
146
147 12 return true;
148 }
149
150 12 bool ZagryadskovMComplexSpMMCCSTBB::PostProcessingImpl() {
151 12 return true;
152 }
153
154 } // namespace zagryadskov_m_complex_spmm_ccs
155