GCC Code Coverage Report


Directory: ./
File: tasks/remizov_k_dense_matrix_multiplication_cannon_algorithm/tbb/src/ops_tbb.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 81 86 94.2%
Functions: 14 16 87.5%
Branches: 58 82 70.7%

Line Branch Exec Source
1 #include "remizov_k_dense_matrix_multiplication_cannon_algorithm/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/blocked_range2d.h>
4 #include <tbb/parallel_for.h>
5
6 #include <cstddef>
7 #include <utility>
8 #include <vector>
9
10 #include "remizov_k_dense_matrix_multiplication_cannon_algorithm/common/include/common.hpp"
11
12 namespace remizov_k_dense_matrix_multiplication_cannon_algorithm {
13
14 32 RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb(
15
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 32 }
19
20 32 bool RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::ValidationImpl() {
21 const auto &input_data = GetInput();
22
23 32 int block_dim = std::get<0>(input_data);
24 const auto &mat_a = std::get<1>(input_data);
25 const auto &mat_b = std::get<2>(input_data);
26
27
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (block_dim <= 0) {
28 return false;
29 }
30
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 if (mat_a.empty() || mat_b.empty()) {
31 return false;
32 }
33
34 size_t n = mat_a.size();
35
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (n != mat_a[0].size()) {
36 return false;
37 }
38
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 if (n != mat_b.size() || n != mat_b[0].size()) {
39 return false;
40 }
41
42 32 return (n % static_cast<size_t>(block_dim) == 0);
43 }
44
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 bool RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::PreProcessingImpl() {
46 GetOutput().clear();
47 32 return true;
48 }
49
50 228 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::MultiplyBlock(const std::vector<std::vector<double>> &a,
51 const std::vector<std::vector<double>> &b,
52 std::vector<std::vector<double>> &c,
53 int block_size) {
54
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 228 times.
720 for (int i = 0; i < block_size; ++i) {
55
2/2
✓ Branch 0 taken 1284 times.
✓ Branch 1 taken 492 times.
1776 for (int j = 0; j < block_size; ++j) {
56 double accumulator = 0.0;
57
2/2
✓ Branch 0 taken 3852 times.
✓ Branch 1 taken 1284 times.
5136 for (int k = 0; k < block_size; ++k) {
58 3852 accumulator += a[i][k] * b[k][j];
59 }
60 1284 c[i][j] += accumulator;
61 }
62 }
63 228 }
64
65 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::ShiftBlocksLeft(
66 std::vector<std::vector<std::vector<std::vector<double>>>> &matrix_blocks, int block_count) {
67 // Parallelize over rows; each row shift is independent
68 28 tbb::parallel_for(0, block_count, [&](int i) {
69 56 auto first_element = std::move(matrix_blocks[i][0]);
70
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 56 times.
112 for (int j = 1; j < block_count; ++j) {
71 56 matrix_blocks[i][j - 1] = std::move(matrix_blocks[i][j]);
72 }
73 56 matrix_blocks[i][block_count - 1] = std::move(first_element);
74 56 });
75 }
76
77 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::ShiftBlocksUp(
78 std::vector<std::vector<std::vector<std::vector<double>>>> &matrix_blocks, int block_count) {
79 // Parallelize over columns; each column shift is independent
80 tbb::parallel_for(0, block_count, [&](int j) {
81 56 auto first_element = std::move(matrix_blocks[0][j]);
82
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 56 times.
112 for (int i = 1; i < block_count; ++i) {
83 56 matrix_blocks[i - 1][j] = std::move(matrix_blocks[i][j]);
84 }
85 56 matrix_blocks[block_count - 1][j] = std::move(first_element);
86 56 });
87 }
88
89 32 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::RunCannonCycle(
90 std::vector<std::vector<std::vector<std::vector<double>>>> &a_blocks,
91 std::vector<std::vector<std::vector<std::vector<double>>>> &b_blocks,
92 std::vector<std::vector<std::vector<std::vector<double>>>> &c_blocks, int block_size, int block_count) {
93
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 32 times.
92 for (int step = 0; step < block_count; ++step) {
94 // Parallel multiplication of all block pairs
95 60 tbb::parallel_for(tbb::blocked_range2d<int>(0, block_count, 0, block_count),
96 288 [&](const tbb::blocked_range2d<int> &r) {
97
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 228 times.
456 for (int i = r.rows().begin(); i != r.rows().end(); ++i) {
98
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 228 times.
456 for (int j = r.cols().begin(); j != r.cols().end(); ++j) {
99 228 MultiplyBlock(a_blocks[i][j], b_blocks[i][j], c_blocks[i][j], block_size);
100 }
101 }
102 228 });
103
104
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 32 times.
60 if (step < block_count - 1) {
105 28 ShiftBlocksLeft(a_blocks, block_count);
106 28 ShiftBlocksUp(b_blocks, block_count);
107 }
108 }
109 32 }
110
111 32 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::InitializeBlocks(
112 const std::vector<std::vector<double>> &matrix_a, const std::vector<std::vector<double>> &matrix_b,
113 std::vector<std::vector<std::vector<std::vector<double>>>> &a_blocks,
114 std::vector<std::vector<std::vector<std::vector<double>>>> &b_blocks, int block_size, int block_count) {
115 148 tbb::parallel_for(tbb::blocked_range2d<int>(0, block_count, 0, block_count), [&](const tbb::blocked_range2d<int> &r) {
116
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 116 times.
232 for (int i = r.rows().begin(); i != r.rows().end(); ++i) {
117
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 116 times.
232 for (int j = r.cols().begin(); j != r.cols().end(); ++j) {
118 116 int shift_value = (i + j) % block_count;
119
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 116 times.
368 for (int bi = 0; bi < block_size; ++bi) {
120
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 252 times.
912 for (int bj = 0; bj < block_size; ++bj) {
121 660 a_blocks[i][j][bi][bj] = matrix_a[(i * block_size) + bi][(shift_value * block_size) + bj];
122 660 b_blocks[i][j][bi][bj] = matrix_b[(shift_value * block_size) + bi][(j * block_size) + bj];
123 }
124 }
125 }
126 }
127 116 });
128 32 }
129
130 32 void RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::AssembleOutput(
131 std::vector<std::vector<std::vector<std::vector<double>>>> &c_blocks, std::vector<std::vector<double>> &output,
132 int block_size, int block_count) {
133 148 tbb::parallel_for(tbb::blocked_range2d<int>(0, block_count, 0, block_count), [&](const tbb::blocked_range2d<int> &r) {
134
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 116 times.
232 for (int i = r.rows().begin(); i != r.rows().end(); ++i) {
135
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 116 times.
232 for (int j = r.cols().begin(); j != r.cols().end(); ++j) {
136
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 116 times.
368 for (int bi = 0; bi < block_size; ++bi) {
137
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 252 times.
912 for (int bj = 0; bj < block_size; ++bj) {
138 660 output[(i * block_size) + bi][(j * block_size) + bj] = c_blocks[i][j][bi][bj];
139 }
140 }
141 }
142 }
143 116 });
144 32 }
145
146 32 bool RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::RunImpl() {
147 const auto &params = GetInput();
148
149 32 int block_dim = std::get<0>(params);
150 const auto &source_a = std::get<1>(params);
151 const auto &source_b = std::get<2>(params);
152
153 32 int matrix_size = static_cast<int>(source_a.size());
154 32 int blocks_per_dim = matrix_size / block_dim;
155
156 std::vector<std::vector<std::vector<std::vector<double>>>> blocks_a(
157 blocks_per_dim,
158 32 std::vector<std::vector<std::vector<double>>>(
159
3/6
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
64 blocks_per_dim, std::vector<std::vector<double>>(block_dim, std::vector<double>(block_dim, 0.0))));
160
161 std::vector<std::vector<std::vector<std::vector<double>>>> blocks_b(
162 blocks_per_dim,
163 32 std::vector<std::vector<std::vector<double>>>(
164
4/8
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
64 blocks_per_dim, std::vector<std::vector<double>>(block_dim, std::vector<double>(block_dim, 0.0))));
165
166 std::vector<std::vector<std::vector<std::vector<double>>>> blocks_c(
167 blocks_per_dim,
168 32 std::vector<std::vector<std::vector<double>>>(
169
4/8
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
64 blocks_per_dim, std::vector<std::vector<double>>(block_dim, std::vector<double>(block_dim, 0.0))));
170
171
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 InitializeBlocks(source_a, source_b, blocks_a, blocks_b, block_dim, blocks_per_dim);
172
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 RunCannonCycle(blocks_a, blocks_b, blocks_c, block_dim, blocks_per_dim);
173
174
2/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
32 std::vector<std::vector<double>> result(matrix_size, std::vector<double>(matrix_size, 0.0));
175
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 AssembleOutput(blocks_c, result, block_dim, blocks_per_dim);
176
177 32 GetOutput() = std::move(result);
178 32 return true;
179 32 }
180
181 32 bool RemizovKDenseMatrixMultiplicationCannonAlgorithmTbb::PostProcessingImpl() {
182 32 return true;
183 }
184
185 } // namespace remizov_k_dense_matrix_multiplication_cannon_algorithm
186