From 25365e02d85e6ad63bb573494d6389ba60731583 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 17:54:18 +0300 Subject: [PATCH 01/33] seq version init commit --- .../common/include/common.hpp | 151 ++++++++++++++++ tasks/kurpiakov_a_sp_comp_mat_mul/info.json | 9 + .../seq/include/ops_seq.hpp | 21 +++ .../seq/src/ops_seq.cpp | 63 +++++++ .../kurpiakov_a_sp_comp_mat_mul/settings.json | 10 ++ .../tests/functional/main.cpp | 170 ++++++++++++++++++ .../tests/performance/main.cpp | 76 ++++++++ 7 files changed, 500 insertions(+) create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/info.json create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/settings.json create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp new file mode 100644 index 000000000..d3c475dad --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -0,0 +1,151 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "task/include/task.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +template +class Complex { + public: + T _re; + T _im; + + Complex() : _re(T(0)), _im(T(0)) {} + Complex(T r, T i) : _re(r), _im(i) {} + + Complex operator+(const Complex& other) const { + return {_re + other._re, _im + other._im}; + } + + Complex operator-(const Complex& other) const { + return {_re - other._re, _im - other._im}; + } + + Complex operator*(const Complex& other) const { + return {_re * other._re - _im * other._im, _re * other._im + _im * other._re}; + } + + Complex& operator+=(const Complex& other) { + _re += other._re; + _im += other._im; + return *this; + } + + bool operator==(const Complex& other) const { + constexpr double kEps = 1e-9; + return std::abs(_re - other._re) < kEps && std::abs(_im - other._im) < kEps; + } + + bool operator!=(const Complex& other) const { + return !(*this == other); + } +}; + +template +class CSRMatrix { + public: + int _rows; + int _cols; + std::vector> _values; + std::vector _col_indices; + std::vector _row_ptr; + + CSRMatrix() : _rows(0), _cols(0), _row_ptr(1, 0) {} + + CSRMatrix(int r, int c) : _rows(r), _cols(c), _row_ptr(r + 1, 0) {} + + CSRMatrix(int r, int c, std::vector> vals, std::vector col_idx, std::vector rp) + : _rows(r), _cols(c), _values(std::move(vals)), _col_indices(std::move(col_idx)), _row_ptr(std::move(rp)) {} + + bool operator==(const CSRMatrix& other) const { + if (_rows != other._rows || _cols != other._cols) { + return false; + } + if (_row_ptr != other._row_ptr || _col_indices != other._col_indices) { + return false; + } + if (_values.size() != other._values.size()) { + return false; + } + for (size_t i = 0; i < _values.size(); ++i) { + if (_values[i] != other._values[i]) { + return false; + } + } + return true; + } + + bool operator!=(const CSRMatrix& other) const { + return !(*this == other); + } + + CSRMatrix Multiply(const CSRMatrix& other) const { + if (_cols != other._rows) { + return {}; + } + + CSRMatrix result(_rows, other._cols); + + std::vector> row_acc(other._cols); + std::vector row_used(other._cols, false); + + for (int i = 0; i < _rows; ++i) { + std::vector used_cols; + used_cols.reserve(other._cols); + + for (int ja = _row_ptr[i]; ja < _row_ptr[i + 1]; ++ja) { + int ka = _col_indices[ja]; + const Complex& a_val = _values[ja]; + + for (int jb = other._row_ptr[ka]; jb < other._row_ptr[ka + 1]; ++jb) { + int cb = other._col_indices[jb]; + const Complex& b_val = other._values[jb]; + + if (!row_used[cb]) { + row_used[cb] = true; + row_acc[cb] = Complex(); + used_cols.push_back(cb); + } + row_acc[cb] += a_val * b_val; + } + } + + std::sort(used_cols.begin(), used_cols.end()); + + for (int c : used_cols) { + result._values.push_back(row_acc[c]); + result._col_indices.push_back(c); + row_used[c] = false; + } + result._row_ptr[i + 1] = static_cast(result._values.size()); + } + + return result; + } + + std::vector> ToDense() const { + std::vector> dense(_rows * _cols); + for (int i = 0; i < _rows; ++i) { + for (int j = _row_ptr[i]; j < _row_ptr[i + 1]; ++j) { + dense[i * _cols + _col_indices[j]] = _values[j]; + } + } + return dense; + } +}; + +using ComplexD = Complex; +using SparseMatrix = CSRMatrix; +using InType = std::pair; +using OutType = SparseMatrix; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/info.json b/tasks/kurpiakov_a_sp_comp_mat_mul/info.json new file mode 100644 index 000000000..33e6a058d --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Алексей", + "group_number": "3823Б1ФИ3", + "last_name": "Курпяков", + "middle_name": "Георгиевич", + "task_number": "1" + } +} diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp new file mode 100644 index 000000000..682d5c516 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiskovACRSMatMulSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit KurpiskovACRSMatMulSEQ(const InType& in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp new file mode 100644 index 000000000..83052e312 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -0,0 +1,63 @@ +#include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +KurpiskovACRSMatMulSEQ::KurpiskovACRSMatMulSEQ(const InType& in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiskovACRSMatMulSEQ::ValidationImpl() { + const auto& [a, b] = GetInput(); + + if (a._rows <= 0 || a._cols <= 0 || b._rows <= 0 || b._cols <= 0) { + return false; + } + + if (a._cols != b._rows) { + return false; + } + + for (int i = 0; i < a._rows; ++i) { + for (int j = a._row_ptr[i]; j < a._row_ptr[i + 1]; ++j) { + if (a._col_indices[j] < 0 || a._col_indices[j] >= a._cols) { + return false; + } + } + } + + if (static_cast(b._row_ptr.size()) != b._rows + 1) { + return false; + } + + if (b._row_ptr[0] != 0) { + return false; + } + + for (int i = 0; i < b._rows; ++i) { + for (int j = b._row_ptr[i]; j < b._row_ptr[i + 1]; ++j) { + if (b._col_indices[j] < 0 || b._col_indices[j] >= b._cols) { + return false; + } + } + } + + return true; +} + +bool KurpiskovACRSMatMulSEQ::PreProcessingImpl() { + return true; +} + +bool KurpiskovACRSMatMulSEQ::RunImpl() { + const auto& [a, b] = GetInput(); + GetOutput() = a.Multiply(b); + return true; +} + +bool KurpiskovACRSMatMulSEQ::PostProcessingImpl() { + return true; +} + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/settings.json b/tasks/kurpiakov_a_sp_comp_mat_mul/settings.json new file mode 100644 index 000000000..0be0208fc --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/settings.json @@ -0,0 +1,10 @@ +{ + "tasks": { + "all": "enabled", + "omp": "enabled", + "seq": "enabled", + "stl": "enabled", + "tbb": "enabled" + }, + "tasks_type": "threads" +} diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp new file mode 100644 index 000000000..dc90cbffe --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -0,0 +1,170 @@ +#include + +#include +#include +#include +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType& test_param) { + return std::get<1>(test_param); + } + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(params); + expected_output_ = std::get<2>(params); + } + + bool CheckTestOutputData(OutType& output_data) final { + return expected_output_ == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_; +}; + +namespace { + +// Test 1: Identity * A = A +InType MakeIdentityTest() { + SparseMatrix eye(2, 2, {ComplexD(1, 0), ComplexD(1, 0)}, {0, 1}, {0, 1, 2}); + SparseMatrix a(2, 2, {ComplexD(1, 0), ComplexD(2, 1), ComplexD(3, 0)}, {0, 1, 1}, {0, 2, 3}); + return {eye, a}; +} +OutType MakeIdentityExpected() { + return SparseMatrix(2, 2, {ComplexD(1, 0), ComplexD(2, 1), ComplexD(3, 0)}, {0, 1, 1}, {0, 2, 3}); +} + +// Test 2: A * Zero = Zero +InType MakeZeroTest() { + SparseMatrix a(2, 2, {ComplexD(1, 0), ComplexD(2, 1)}, {0, 1}, {0, 1, 2}); + SparseMatrix zero(2, 2); + return {a, zero}; +} +OutType MakeZeroExpected() { + return SparseMatrix(2, 2); +} + +// Test 3: Diagonal * Diagonal +InType MakeDiagTest() { + SparseMatrix a(2, 2, {ComplexD(1, 1), ComplexD(2, 0)}, {0, 1}, {0, 1, 2}); + SparseMatrix b(2, 2, {ComplexD(2, 0), ComplexD(0, 1)}, {0, 1}, {0, 1, 2}); + return {a, b}; +} +OutType MakeDiagExpected() { + return SparseMatrix(2, 2, {ComplexD(2, 2), ComplexD(0, 2)}, {0, 1}, {0, 1, 2}); +} + +// Test 4: General 2x2 complex +InType MakeGeneralTest() { + SparseMatrix a(2, 2, {ComplexD(1, 1), ComplexD(1, -1)}, {0, 1}, {0, 1, 2}); + SparseMatrix b(2, 2, {ComplexD(2, 0), ComplexD(3, 1)}, {0, 1}, {0, 1, 2}); + return {a, b}; +} +OutType MakeGeneralExpected() { + return SparseMatrix(2, 2, {ComplexD(2, 2), ComplexD(4, -2)}, {0, 1}, {0, 1, 2}); +} + +// Test 5: Scalar i * i = -1 +InType MakeScalarITest() { + SparseMatrix si(1, 1, {ComplexD(0, 1)}, {0}, {0, 1}); + return {si, si}; +} +OutType MakeScalarIExpected() { + return SparseMatrix(1, 1, {ComplexD(-1, 0)}, {0}, {0, 1}); +} + +// Test 6: Scalar (3+4i)*(1-2i) = 11-2i +InType MakeScalarComplexTest() { + SparseMatrix a(1, 1, {ComplexD(3, 4)}, {0}, {0, 1}); + SparseMatrix b(1, 1, {ComplexD(1, -2)}, {0}, {0, 1}); + return {a, b}; +} +OutType MakeScalarComplexExpected() { + return SparseMatrix(1, 1, {ComplexD(11, -2)}, {0}, {0, 1}); +} + +// Test 7: Rectangular A(2x3) * B(3x2) +InType MakeRectTest() { + SparseMatrix a(2, 3, {ComplexD(1, 0), ComplexD(2, 0), ComplexD(1, 0)}, {0, 2, 1}, {0, 2, 3}); + SparseMatrix b(3, 2, {ComplexD(1, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(1, 0)}, {0, 1, 0, 1}, {0, 2, 3, 4}); + return {a, b}; +} +OutType MakeRectExpected() { + return SparseMatrix(2, 2, {ComplexD(1, 0), ComplexD(3, 0), ComplexD(1, 0)}, {0, 1, 0}, {0, 2, 3}); +} + +// Test 8: Both empty 3x3 +InType MakeEmptyTest() { + SparseMatrix empty(3, 3); + return {empty, empty}; +} +OutType MakeEmptyExpected() { + return SparseMatrix(3, 3); +} + +// Test 9: Dense 2x2 +InType MakeDenseTest() { + SparseMatrix a(2, 2, {ComplexD(1, 0), ComplexD(2, 0), ComplexD(3, 0), ComplexD(4, 0)}, {0, 1, 0, 1}, {0, 2, 4}); + SparseMatrix b(2, 2, {ComplexD(5, 0), ComplexD(6, 0), ComplexD(7, 0), ComplexD(8, 0)}, {0, 1, 0, 1}, {0, 2, 4}); + return {a, b}; +} +OutType MakeDenseExpected() { + return SparseMatrix(2, 2, {ComplexD(19, 0), ComplexD(22, 0), ComplexD(43, 0), ComplexD(50, 0)}, {0, 1, 0, 1}, + {0, 2, 4}); +} + +// Test 10: Row * Column = scalar +InType MakeRowColTest() { + SparseMatrix a(1, 3, {ComplexD(1, 0), ComplexD(2, 0), ComplexD(3, 0)}, {0, 1, 2}, {0, 3}); + SparseMatrix b(3, 1, {ComplexD(4, 0), ComplexD(5, 0), ComplexD(6, 0)}, {0, 0, 0}, {0, 1, 2, 3}); + return {a, b}; +} +OutType MakeRowColExpected() { + return SparseMatrix(1, 1, {ComplexD(32, 0)}, {0}, {0, 1}); +} + +const std::array kTestParam = { + std::make_tuple(MakeIdentityTest(), "identity_2x2", MakeIdentityExpected()), + std::make_tuple(MakeZeroTest(), "zero_2x2", MakeZeroExpected()), + std::make_tuple(MakeDiagTest(), "diag_2x2", MakeDiagExpected()), + std::make_tuple(MakeGeneralTest(), "general_2x2", MakeGeneralExpected()), + std::make_tuple(MakeScalarITest(), "scalar_i_squared", MakeScalarIExpected()), + std::make_tuple(MakeScalarComplexTest(), "scalar_complex", MakeScalarComplexExpected()), + std::make_tuple(MakeRectTest(), "rect_2x3_times_3x2", MakeRectExpected()), + std::make_tuple(MakeEmptyTest(), "both_empty_3x3", MakeEmptyExpected()), + std::make_tuple(MakeDenseTest(), "dense_2x2", MakeDenseExpected()), + std::make_tuple(MakeRowColTest(), "row_times_col", MakeRowColExpected()), +}; + +TEST_P(KurpiakovRunFuncTestsThreads, SparseMatMulFromParams) { + ExecuteTest(GetParam()); +} + +const auto kTestTasksList = std::tuple_cat( + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); +const auto kPerfTestName = KurpiakovRunFuncTestsThreads::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(SparseMatMulSeqTests, KurpiakovRunFuncTestsThreads, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp new file mode 100644 index 000000000..463d1e2a4 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -0,0 +1,76 @@ +#include + +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +namespace { + +SparseMatrix MakeTridiagonal(int n) { + SparseMatrix m; + m._rows = n; + m._cols = n; + m._row_ptr.resize(n + 1, 0); + + for (int i = 0; i < n; ++i) { + if (i > 0) { + m._values.emplace_back(0, 1); + m._col_indices.push_back(i - 1); + } + m._values.emplace_back(2, 1); + m._col_indices.push_back(i); + if (i < n - 1) { + m._values.emplace_back(1, 0); + m._col_indices.push_back(i + 1); + } + m._row_ptr[i + 1] = static_cast(m._values.size()); + } + return m; +} + +} // namespace + +class KurpiakovRunPerfTests : public ppc::util::BaseRunPerfTests { + InType input_data_; + OutType expected_output_; + + void SetUp() override { + constexpr int kSize = 500; + + auto a = MakeTridiagonal(kSize); + auto b = MakeTridiagonal(kSize); + + expected_output_ = a.Multiply(b); + input_data_ = {std::move(a), std::move(b)}; + } + + bool CheckTestOutputData(OutType& output_data) final { + return expected_output_ == output_data; + } + + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { + ExecuteTest(GetParam()); +} + +namespace { + +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); +const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(SparseMatMulPerfTests, KurpiakovRunPerfTests, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace kurpiakov_a_sp_comp_mat_mul From 5aaa9f390bc30a23cbea4855311ba09675413cfd Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 18:03:10 +0300 Subject: [PATCH 02/33] seq version init commit --- .../tests/functional/main.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index dc90cbffe..27c3965eb 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -41,7 +41,6 @@ class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests kTestParam = { std::make_tuple(MakeIdentityTest(), "identity_2x2", MakeIdentityExpected()), std::make_tuple(MakeZeroTest(), "zero_2x2", MakeZeroExpected()), From 6d67784a5b7925ac9e1e915aeae1131a95b8d2f3 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 18:04:12 +0300 Subject: [PATCH 03/33] fix clang-format --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 27c3965eb..7d8324ac0 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -130,7 +130,6 @@ OutType MakeRowColExpected() { return SparseMatrix(1, 1, {ComplexD(32, 0)}, {0}, {0, 1}); } - const std::array kTestParam = { std::make_tuple(MakeIdentityTest(), "identity_2x2", MakeIdentityExpected()), std::make_tuple(MakeZeroTest(), "zero_2x2", MakeZeroExpected()), From cf2e469a100decc6b753d978e8cfc93d54a70402 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 18:15:34 +0300 Subject: [PATCH 04/33] fix clang-tidy --- .../common/include/common.hpp | 91 ++++++++-------- .../seq/src/ops_seq.cpp | 58 +++++----- .../tests/functional/main.cpp | 102 +++++++++++++++--- .../tests/performance/main.cpp | 20 ++-- 4 files changed, 177 insertions(+), 94 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp index d3c475dad..98d635d52 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -14,33 +15,33 @@ namespace kurpiakov_a_sp_comp_mat_mul { template class Complex { public: - T _re; - T _im; + T re; + T im; - Complex() : _re(T(0)), _im(T(0)) {} - Complex(T r, T i) : _re(r), _im(i) {} + Complex() : re(T(0)), im(T(0)) {} + Complex(T r, T i) : re(r), im(i) {} Complex operator+(const Complex& other) const { - return {_re + other._re, _im + other._im}; + return {re + other.re, im + other.im}; } Complex operator-(const Complex& other) const { - return {_re - other._re, _im - other._im}; + return {re - other.re, im - other.im}; } Complex operator*(const Complex& other) const { - return {_re * other._re - _im * other._im, _re * other._im + _im * other._re}; + return {(re * other.re) - (im * other.im), (re * other.im) + (im * other.re)}; } Complex& operator+=(const Complex& other) { - _re += other._re; - _im += other._im; + re += other.re; + im += other.im; return *this; } bool operator==(const Complex& other) const { constexpr double kEps = 1e-9; - return std::abs(_re - other._re) < kEps && std::abs(_im - other._im) < kEps; + return std::abs(re - other.re) < kEps && std::abs(im - other.im) < kEps; } bool operator!=(const Complex& other) const { @@ -51,31 +52,31 @@ class Complex { template class CSRMatrix { public: - int _rows; - int _cols; - std::vector> _values; - std::vector _col_indices; - std::vector _row_ptr; + int rows; + int cols; + std::vector> values; + std::vector col_indices; + std::vector row_ptr; - CSRMatrix() : _rows(0), _cols(0), _row_ptr(1, 0) {} + CSRMatrix() : rows(0), cols(0), row_ptr(1, 0) {} - CSRMatrix(int r, int c) : _rows(r), _cols(c), _row_ptr(r + 1, 0) {} + CSRMatrix(int r, int c) : rows(r), cols(c), row_ptr(r + 1, 0) {} CSRMatrix(int r, int c, std::vector> vals, std::vector col_idx, std::vector rp) - : _rows(r), _cols(c), _values(std::move(vals)), _col_indices(std::move(col_idx)), _row_ptr(std::move(rp)) {} + : rows(r), cols(c), values(std::move(vals)), col_indices(std::move(col_idx)), row_ptr(std::move(rp)) {} bool operator==(const CSRMatrix& other) const { - if (_rows != other._rows || _cols != other._cols) { + if (rows != other.rows || cols != other.cols) { return false; } - if (_row_ptr != other._row_ptr || _col_indices != other._col_indices) { + if (row_ptr != other.row_ptr || col_indices != other.col_indices) { return false; } - if (_values.size() != other._values.size()) { + if (values.size() != other.values.size()) { return false; } - for (size_t i = 0; i < _values.size(); ++i) { - if (_values[i] != other._values[i]) { + for (size_t i = 0; i < values.size(); ++i) { + if (values[i] != other.values[i]) { return false; } } @@ -86,27 +87,27 @@ class CSRMatrix { return !(*this == other); } - CSRMatrix Multiply(const CSRMatrix& other) const { - if (_cols != other._rows) { + [[nodiscard]] CSRMatrix Multiply(const CSRMatrix& other) const { + if (cols != other.rows) { return {}; } - CSRMatrix result(_rows, other._cols); + CSRMatrix result(rows, other.cols); - std::vector> row_acc(other._cols); - std::vector row_used(other._cols, false); + std::vector> row_acc(other.cols); + std::vector row_used(other.cols, false); - for (int i = 0; i < _rows; ++i) { + for (int i = 0; i < rows; ++i) { std::vector used_cols; - used_cols.reserve(other._cols); + used_cols.reserve(other.cols); - for (int ja = _row_ptr[i]; ja < _row_ptr[i + 1]; ++ja) { - int ka = _col_indices[ja]; - const Complex& a_val = _values[ja]; + for (int ja = row_ptr[i]; ja < row_ptr[i + 1]; ++ja) { + int ka = col_indices[ja]; + const Complex& a_val = values[ja]; - for (int jb = other._row_ptr[ka]; jb < other._row_ptr[ka + 1]; ++jb) { - int cb = other._col_indices[jb]; - const Complex& b_val = other._values[jb]; + for (int jb = other.row_ptr[ka]; jb < other.row_ptr[ka + 1]; ++jb) { + int cb = other.col_indices[jb]; + const Complex& b_val = other.values[jb]; if (!row_used[cb]) { row_used[cb] = true; @@ -117,24 +118,24 @@ class CSRMatrix { } } - std::sort(used_cols.begin(), used_cols.end()); + std::ranges::sort(used_cols); for (int c : used_cols) { - result._values.push_back(row_acc[c]); - result._col_indices.push_back(c); + result.values.push_back(row_acc[c]); + result.col_indices.push_back(c); row_used[c] = false; } - result._row_ptr[i + 1] = static_cast(result._values.size()); + result.row_ptr[i + 1] = static_cast(result.values.size()); } return result; } - std::vector> ToDense() const { - std::vector> dense(_rows * _cols); - for (int i = 0; i < _rows; ++i) { - for (int j = _row_ptr[i]; j < _row_ptr[i + 1]; ++j) { - dense[i * _cols + _col_indices[j]] = _values[j]; + [[nodiscard]] std::vector> ToDense() const { + std::vector> dense(rows * cols); + for (int i = 0; i < rows; ++i) { + for (int j = row_ptr[i]; j < row_ptr[i + 1]; ++j) { + dense[(i * cols) + col_indices[j]] = values[j]; } } return dense; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp index 83052e312..e23cd2125 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -1,51 +1,55 @@ #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" -namespace kurpiakov_a_sp_comp_mat_mul { +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" -KurpiskovACRSMatMulSEQ::KurpiskovACRSMatMulSEQ(const InType& in) { - SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = SparseMatrix(); -} +namespace kurpiakov_a_sp_comp_mat_mul { -bool KurpiskovACRSMatMulSEQ::ValidationImpl() { - const auto& [a, b] = GetInput(); +namespace { - if (a._rows <= 0 || a._cols <= 0 || b._rows <= 0 || b._cols <= 0) { +bool ValidateCSR(const SparseMatrix& m) { + if (m.rows <= 0 || m.cols <= 0) { return false; } - - if (a._cols != b._rows) { + if (static_cast(m.row_ptr.size()) != m.rows + 1) { return false; } - - for (int i = 0; i < a._rows; ++i) { - for (int j = a._row_ptr[i]; j < a._row_ptr[i + 1]; ++j) { - if (a._col_indices[j] < 0 || a._col_indices[j] >= a._cols) { - return false; - } - } + if (m.row_ptr[0] != 0) { + return false; } - - if (static_cast(b._row_ptr.size()) != b._rows + 1) { + if (static_cast(m.values.size()) != m.row_ptr[m.rows]) { return false; } - - if (b._row_ptr[0] != 0) { + if (m.col_indices.size() != m.values.size()) { return false; } - - for (int i = 0; i < b._rows; ++i) { - for (int j = b._row_ptr[i]; j < b._row_ptr[i + 1]; ++j) { - if (b._col_indices[j] < 0 || b._col_indices[j] >= b._cols) { + for (int i = 0; i < m.rows; ++i) { + for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) { + if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) { return false; } } } - return true; } +} // namespace + +KurpiskovACRSMatMulSEQ::KurpiskovACRSMatMulSEQ(const InType& in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiskovACRSMatMulSEQ::ValidationImpl() { + const auto& [a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + bool KurpiskovACRSMatMulSEQ::PreProcessingImpl() { return true; } diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 7d8324ac0..ba011cdb4 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" @@ -41,93 +40,167 @@ class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests kTestParam = { @@ -141,6 +214,11 @@ const std::array kTestParam = { std::make_tuple(MakeEmptyTest(), "both_empty_3x3", MakeEmptyExpected()), std::make_tuple(MakeDenseTest(), "dense_2x2", MakeDenseExpected()), std::make_tuple(MakeRowColTest(), "row_times_col", MakeRowColExpected()), + std::make_tuple(MakeOuterProductTest(), "outer_product", MakeOuterProductExpected()), + std::make_tuple(MakeSparse3x3Test(), "sparse_3x3", MakeSparse3x3Expected()), + std::make_tuple(MakeComplexDenseTest(), "complex_dense_2x2", MakeComplexDenseExpected()), + std::make_tuple(MakeRightIdentityTest(), "right_identity_2x2", MakeRightIdentityExpected()), + std::make_tuple(MakeTridiag4Test(), "tridiag_4x4_times_eye", MakeTridiag4Expected()), }; TEST_P(KurpiakovRunFuncTestsThreads, SparseMatMulFromParams) { diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 463d1e2a4..38eee104f 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -13,22 +13,22 @@ namespace { SparseMatrix MakeTridiagonal(int n) { SparseMatrix m; - m._rows = n; - m._cols = n; - m._row_ptr.resize(n + 1, 0); + m.rows = n; + m.cols = n; + m.row_ptr.resize(n + 1, 0); for (int i = 0; i < n; ++i) { if (i > 0) { - m._values.emplace_back(0, 1); - m._col_indices.push_back(i - 1); + m.values.emplace_back(0, 1); + m.col_indices.push_back(i - 1); } - m._values.emplace_back(2, 1); - m._col_indices.push_back(i); + m.values.emplace_back(2, 1); + m.col_indices.push_back(i); if (i < n - 1) { - m._values.emplace_back(1, 0); - m._col_indices.push_back(i + 1); + m.values.emplace_back(1, 0); + m.col_indices.push_back(i + 1); } - m._row_ptr[i + 1] = static_cast(m._values.size()); + m.row_ptr[i + 1] = static_cast(m.values.size()); } return m; } From 71a3627c52289e08f09d503ad721e5e102a984cd Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 18:33:34 +0300 Subject: [PATCH 05/33] fix clang-tidy --- .../tests/functional/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index ba011cdb4..fc9db7059 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -40,7 +40,6 @@ class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests Date: Thu, 26 Feb 2026 18:43:02 +0300 Subject: [PATCH 06/33] fix clang-tidy --- .../tests/functional/main.cpp | 72 +------------------ 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index fc9db7059..0dd2e6972 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -128,72 +128,7 @@ OutType MakeRowColExpected() { return {1, 1, {ComplexD(32, 0)}, {0}, {0, 1}}; } -// Test 11: Column * Row = outer product 3x3 -InType MakeOuterProductTest() { - SparseMatrix a(3, 1, {ComplexD(1, 0), ComplexD(2, 0), ComplexD(3, 0)}, {0, 0, 0}, {0, 1, 2, 3}); - SparseMatrix b(1, 3, {ComplexD(4, 0), ComplexD(5, 0), ComplexD(6, 0)}, {0, 1, 2}, {0, 3}); - return {a, b}; -} -OutType MakeOuterProductExpected() { - return {3, - 3, - {ComplexD(4, 0), ComplexD(5, 0), ComplexD(6, 0), ComplexD(8, 0), ComplexD(10, 0), ComplexD(12, 0), - ComplexD(12, 0), ComplexD(15, 0), ComplexD(18, 0)}, - {0, 1, 2, 0, 1, 2, 0, 1, 2}, - {0, 3, 6, 9}}; -} - -// Test 12: Sparse 3x3 with few nonzeros -InType MakeSparse3x3Test() { - SparseMatrix a(3, 3, {ComplexD(1, 0), ComplexD(2, 0)}, {2, 0}, {0, 1, 1, 2}); - SparseMatrix b(3, 3, {ComplexD(1, 0), ComplexD(3, 0)}, {0, 2}, {0, 1, 1, 2}); - return {a, b}; -} -OutType MakeSparse3x3Expected() { - return {3, 3, {ComplexD(3, 0), ComplexD(2, 0)}, {2, 0}, {0, 1, 1, 2}}; -} - -// Test 13: Complex dense 2x2 -InType MakeComplexDenseTest() { - SparseMatrix a(2, 2, {ComplexD(1, 2), ComplexD(3, 4), ComplexD(9, 10), ComplexD(11, 12)}, {0, 1, 0, 1}, {0, 2, 4}); - SparseMatrix b(2, 2, {ComplexD(5, 6), ComplexD(7, 8), ComplexD(13, 14), ComplexD(15, 16)}, {0, 1, 0, 1}, {0, 2, 4}); - return {a, b}; -} -OutType MakeComplexDenseExpected() { - return { - 2, 2, {ComplexD(-24, 110), ComplexD(-28, 130), ComplexD(-40, 414), ComplexD(-44, 498)}, {0, 1, 0, 1}, {0, 2, 4}}; -} - -// Test 14: A * Identity = A (right multiply) -InType MakeRightIdentityTest() { - SparseMatrix a(2, 2, {ComplexD(5, -3), ComplexD(7, 2), ComplexD(1, 1)}, {0, 0, 1}, {0, 1, 3}); - SparseMatrix eye(2, 2, {ComplexD(1, 0), ComplexD(1, 0)}, {0, 1}, {0, 1, 2}); - return {a, eye}; -} -OutType MakeRightIdentityExpected() { - return {2, 2, {ComplexD(5, -3), ComplexD(7, 2), ComplexD(1, 1)}, {0, 0, 1}, {0, 1, 3}}; -} - -// Test 15: Tridiagonal 4x4 * Identity -InType MakeTridiag4Test() { - SparseMatrix a(4, 4, - {ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), - ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(2, 0)}, - {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}, {0, 2, 5, 8, 10}); - SparseMatrix eye(4, 4, {ComplexD(1, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(1, 0)}, {0, 1, 2, 3}, - {0, 1, 2, 3, 4}); - return {a, eye}; -} -OutType MakeTridiag4Expected() { - return {4, - 4, - {ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), - ComplexD(2, 0), ComplexD(1, 0), ComplexD(1, 0), ComplexD(2, 0)}, - {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}, - {0, 2, 5, 8, 10}}; -} - -const std::array kTestParam = { +const std::array kTestParam = { std::make_tuple(MakeIdentityTest(), "identity_2x2", MakeIdentityExpected()), std::make_tuple(MakeZeroTest(), "zero_2x2", MakeZeroExpected()), std::make_tuple(MakeDiagTest(), "diag_2x2", MakeDiagExpected()), @@ -204,11 +139,6 @@ const std::array kTestParam = { std::make_tuple(MakeEmptyTest(), "both_empty_3x3", MakeEmptyExpected()), std::make_tuple(MakeDenseTest(), "dense_2x2", MakeDenseExpected()), std::make_tuple(MakeRowColTest(), "row_times_col", MakeRowColExpected()), - std::make_tuple(MakeOuterProductTest(), "outer_product", MakeOuterProductExpected()), - std::make_tuple(MakeSparse3x3Test(), "sparse_3x3", MakeSparse3x3Expected()), - std::make_tuple(MakeComplexDenseTest(), "complex_dense_2x2", MakeComplexDenseExpected()), - std::make_tuple(MakeRightIdentityTest(), "right_identity_2x2", MakeRightIdentityExpected()), - std::make_tuple(MakeTridiag4Test(), "tridiag_4x4_times_eye", MakeTridiag4Expected()), }; TEST_P(KurpiakovRunFuncTestsThreads, SparseMatMulFromParams) { From a114548a164ede5a7069263d3a9e6256f033b35b Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 19:37:50 +0300 Subject: [PATCH 07/33] fix clang tidy --- .../common/include/common.hpp | 22 +++++++++---------- .../seq/include/ops_seq.hpp | 2 +- .../seq/src/ops_seq.cpp | 8 +++---- .../tests/functional/main.cpp | 2 +- .../tests/performance/main.cpp | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp index 98d635d52..9b407ba0c 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -21,30 +21,30 @@ class Complex { Complex() : re(T(0)), im(T(0)) {} Complex(T r, T i) : re(r), im(i) {} - Complex operator+(const Complex& other) const { + Complex operator+(const Complex &other) const { return {re + other.re, im + other.im}; } - Complex operator-(const Complex& other) const { + Complex operator-(const Complex &other) const { return {re - other.re, im - other.im}; } - Complex operator*(const Complex& other) const { + Complex operator*(const Complex &other) const { return {(re * other.re) - (im * other.im), (re * other.im) + (im * other.re)}; } - Complex& operator+=(const Complex& other) { + Complex &operator+=(const Complex &other) { re += other.re; im += other.im; return *this; } - bool operator==(const Complex& other) const { + bool operator==(const Complex &other) const { constexpr double kEps = 1e-9; return std::abs(re - other.re) < kEps && std::abs(im - other.im) < kEps; } - bool operator!=(const Complex& other) const { + bool operator!=(const Complex &other) const { return !(*this == other); } }; @@ -65,7 +65,7 @@ class CSRMatrix { CSRMatrix(int r, int c, std::vector> vals, std::vector col_idx, std::vector rp) : rows(r), cols(c), values(std::move(vals)), col_indices(std::move(col_idx)), row_ptr(std::move(rp)) {} - bool operator==(const CSRMatrix& other) const { + bool operator==(const CSRMatrix &other) const { if (rows != other.rows || cols != other.cols) { return false; } @@ -83,11 +83,11 @@ class CSRMatrix { return true; } - bool operator!=(const CSRMatrix& other) const { + bool operator!=(const CSRMatrix &other) const { return !(*this == other); } - [[nodiscard]] CSRMatrix Multiply(const CSRMatrix& other) const { + [[nodiscard]] CSRMatrix Multiply(const CSRMatrix &other) const { if (cols != other.rows) { return {}; } @@ -103,11 +103,11 @@ class CSRMatrix { for (int ja = row_ptr[i]; ja < row_ptr[i + 1]; ++ja) { int ka = col_indices[ja]; - const Complex& a_val = values[ja]; + const Complex &a_val = values[ja]; for (int jb = other.row_ptr[ka]; jb < other.row_ptr[ka + 1]; ++jb) { int cb = other.col_indices[jb]; - const Complex& b_val = other.values[jb]; + const Complex &b_val = other.values[jb]; if (!row_used[cb]) { row_used[cb] = true; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp index 682d5c516..a3ad5d2ba 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp @@ -9,7 +9,7 @@ class KurpiskovACRSMatMulSEQ : public BaseTask { static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { return ppc::task::TypeOfTask::kSEQ; } - explicit KurpiskovACRSMatMulSEQ(const InType& in); + explicit KurpiskovACRSMatMulSEQ(const InType &in); private: bool ValidationImpl() override; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp index e23cd2125..a9403839d 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -6,7 +6,7 @@ namespace kurpiakov_a_sp_comp_mat_mul { namespace { -bool ValidateCSR(const SparseMatrix& m) { +bool ValidateCSR(const SparseMatrix &m) { if (m.rows <= 0 || m.cols <= 0) { return false; } @@ -34,14 +34,14 @@ bool ValidateCSR(const SparseMatrix& m) { } // namespace -KurpiskovACRSMatMulSEQ::KurpiskovACRSMatMulSEQ(const InType& in) { +KurpiskovACRSMatMulSEQ::KurpiskovACRSMatMulSEQ(const InType &in) { SetTypeOfTask(GetStaticTypeOfTask()); GetInput() = in; GetOutput() = SparseMatrix(); } bool KurpiskovACRSMatMulSEQ::ValidationImpl() { - const auto& [a, b] = GetInput(); + const auto &[a, b] = GetInput(); if (!ValidateCSR(a) || !ValidateCSR(b)) { return false; @@ -55,7 +55,7 @@ bool KurpiskovACRSMatMulSEQ::PreProcessingImpl() { } bool KurpiskovACRSMatMulSEQ::RunImpl() { - const auto& [a, b] = GetInput(); + const auto &[a, b] = GetInput(); GetOutput() = a.Multiply(b); return true; } diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 0dd2e6972..0360dcdab 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -25,7 +25,7 @@ class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests(params); } - bool CheckTestOutputData(OutType& output_data) final { + bool CheckTestOutputData(OutType &output_data) final { return expected_output_ == output_data; } diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 38eee104f..c00e2c8a2 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -49,7 +49,7 @@ class KurpiakovRunPerfTests : public ppc::util::BaseRunPerfTests Date: Thu, 26 Feb 2026 19:54:29 +0300 Subject: [PATCH 08/33] fix --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 0360dcdab..4c0294cee 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -14,7 +14,7 @@ namespace kurpiakov_a_sp_comp_mat_mul { class KurpiakovRunFuncTestsThreads : public ppc::util::BaseRunFuncTests { public: - static std::string PrintTestParam(const TestType& test_param) { + static std::string PrintTestParam(const TestType &test_param) { return std::get<1>(test_param); } From b337acaa12481729d29907873d37c85ec5fbeb0c Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 20:03:31 +0300 Subject: [PATCH 09/33] fix --- tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp | 1 + tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp index a3ad5d2ba..501ee09f4 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp @@ -1,6 +1,7 @@ #pragma once #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "task/include/task.hpp" namespace kurpiakov_a_sp_comp_mat_mul { diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp index a9403839d..a9386160c 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -16,7 +16,7 @@ bool ValidateCSR(const SparseMatrix &m) { if (m.row_ptr[0] != 0) { return false; } - if (static_cast(m.values.size()) != m.row_ptr[m.rows]) { + if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) { return false; } if (m.col_indices.size() != m.values.size()) { From 827a0a45d50a6e72daed042d4db1e76fb3ee34e0 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 20:09:58 +0300 Subject: [PATCH 10/33] fix --- tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp index a9386160c..0edcd4f5d 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -1,3 +1,5 @@ +#include + #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" From 40c0bcf380abfce1fb50d295f2748dcd7b289d12 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 26 Feb 2026 20:14:32 +0300 Subject: [PATCH 11/33] fix --- tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp index 0edcd4f5d..5bb752c62 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/seq/src/ops_seq.cpp @@ -1,7 +1,7 @@ -#include - #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include + #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" namespace kurpiakov_a_sp_comp_mat_mul { From 15cf3350bd85e1d4914066d5a6b1e35e64433051 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Mon, 13 Apr 2026 19:44:46 +0300 Subject: [PATCH 12/33] Changes to be committed: new file: tasks/kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp new file: tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp modified: tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp modified: tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp --- .../tbb/include/ops_tbb.hpp | 22 +++ .../tbb/src/ops_tbb.cpp | 137 ++++++++++++++++++ .../tests/functional/main.cpp | 4 +- .../tests/performance/main.cpp | 4 +- 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp new file mode 100644 index 000000000..18e545e3d --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiakovACRSMatMulTBB : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kTBB; + } + explicit KurpiakovACRSMatMulTBB(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp new file mode 100644 index 000000000..2a802a620 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp @@ -0,0 +1,137 @@ +#include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" + +#include + +#include +#include +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +namespace { + +bool ValidateCSR(const SparseMatrix &m) { + if (m.rows <= 0 || m.cols <= 0) { + return false; + } + if (static_cast(m.row_ptr.size()) != m.rows + 1) { + return false; + } + if (m.row_ptr[0] != 0) { + return false; + } + if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) { + return false; + } + if (m.col_indices.size() != m.values.size()) { + return false; + } + for (int i = 0; i < m.rows; ++i) { + for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) { + if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) { + return false; + } + } + } + return true; +} + +} // namespace + +KurpiakovACRSMatMulTBB::KurpiakovACRSMatMulTBB(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulTBB::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulTBB::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulTBB::RunImpl() { + const auto &[a, b] = GetInput(); + const int rows = a.rows; + const int cols = b.cols; + + std::vector> row_values(rows); + std::vector> row_cols(rows); + + tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { + std::vector row_acc(cols); + std::vector row_used(cols, 0); + std::vector used_cols; + + for (int i = range.begin(); i < range.end(); ++i) { + used_cols.clear(); + + for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; + + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; + + if (row_used[cb] == 0) { + row_used[cb] = 1; + row_acc[cb] = ComplexD(); + used_cols.push_back(cb); + } + row_acc[cb] += a_val * b_val; + } + } + + std::ranges::sort(used_cols); + + auto ¤t_row_values = row_values[i]; + auto ¤t_row_cols = row_cols[i]; + current_row_values.clear(); + current_row_cols.clear(); + current_row_values.reserve(used_cols.size()); + current_row_cols.reserve(used_cols.size()); + + for (int c : used_cols) { + current_row_values.push_back(row_acc[c]); + current_row_cols.push_back(c); + row_used[c] = 0; + } + } + }); + + SparseMatrix result(rows, cols); + std::size_t total_nnz = 0; + for (int i = 0; i < rows; ++i) { + total_nnz += row_values[i].size(); + } + + result.values.reserve(total_nnz); + result.col_indices.reserve(total_nnz); + + for (int i = 0; i < rows; ++i) { + result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); + result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); + result.row_ptr[i + 1] = static_cast(result.values.size()); + } + + GetOutput() = std::move(result); + return true; +} + +bool KurpiakovACRSMatMulTBB::PostProcessingImpl() { + return true; +} + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 4c0294cee..094d1ae05 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -146,7 +146,9 @@ TEST_P(KurpiakovRunFuncTestsThreads, SparseMatMulFromParams) { } const auto kTestTasksList = std::tuple_cat( - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); const auto kPerfTestName = KurpiakovRunFuncTestsThreads::PrintFuncTestName; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index c00e2c8a2..df40d01d6 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -64,8 +64,8 @@ TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { namespace { -const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 45bdf7a8dcd6c7c1a034159a6b7bf3438537b278 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Mon, 13 Apr 2026 19:48:43 +0300 Subject: [PATCH 13/33] Changes to be committed: new file: tasks/kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp new file: tasks/kurpiakov_a_sp_comp_mat_mul/omp/src/ops_omp.cpp --- .../omp/include/ops_omp.hpp | 22 ++++++ .../omp/src/ops_omp.cpp | 70 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/omp/src/ops_omp.cpp diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp new file mode 100644 index 000000000..a4aa74df7 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiakovACRSMatMulOMP : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kOMP; + } + explicit KurpiakovACRSMatMulOMP(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/omp/src/ops_omp.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/omp/src/ops_omp.cpp new file mode 100644 index 000000000..49b72b9f4 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/omp/src/ops_omp.cpp @@ -0,0 +1,70 @@ +#include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" + +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +namespace { + +bool ValidateCSR(const SparseMatrix &m) { + if (m.rows <= 0 || m.cols <= 0) { + return false; + } + if (static_cast(m.row_ptr.size()) != m.rows + 1) { + return false; + } + if (m.row_ptr[0] != 0) { + return false; + } + if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) { + return false; + } + if (m.col_indices.size() != m.values.size()) { + return false; + } + for (int i = 0; i < m.rows; ++i) { + for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) { + if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) { + return false; + } + } + } + return true; +} + +} // namespace + +KurpiakovACRSMatMulOMP::KurpiakovACRSMatMulOMP(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulOMP::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulOMP::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulOMP::RunImpl() { + const auto &[a, b] = GetInput(); + GetOutput() = a.OMPMultiply(b); + return true; +} + +bool KurpiakovACRSMatMulOMP::PostProcessingImpl() { + return true; +} + +} // namespace kurpiakov_a_sp_comp_mat_mul From 8d8248466e45fda51187119006213aabd95c331d Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Mon, 13 Apr 2026 19:57:41 +0300 Subject: [PATCH 14/33] fix clang-format --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index df40d01d6..aa1fb8504 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -64,8 +64,9 @@ TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { namespace { -const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 14459269eb4574bd02712291727f5c82701d3b91 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:01:20 +0300 Subject: [PATCH 15/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index df40d01d6..aa1fb8504 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -64,8 +64,9 @@ TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { namespace { -const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); +const auto kAllPerfTasks = + ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From a7cdb5123f98ddcdf19a9b6acf2d7c9d59fcdb84 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 08:48:48 +0300 Subject: [PATCH 16/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 094d1ae05..9e97b2648 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -6,7 +6,9 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" From ac77f0c2b51fa73563dd81cbb862416dee311f29 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 08:49:03 +0300 Subject: [PATCH 17/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index aa1fb8504..645241729 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -4,7 +4,9 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" #include "util/include/perf_test_util.hpp" namespace kurpiakov_a_sp_comp_mat_mul { From f5816357f0948b44354455a6104ed24ff7cd7989 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:54:30 +0300 Subject: [PATCH 18/33] Update common.hpp --- .../common/include/common.hpp | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp index 9b407ba0c..3dc8f9511 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -131,6 +131,88 @@ class CSRMatrix { return result; } + private: + static void ProcessRow(int i, const CSRMatrix &self, const CSRMatrix &other, std::vector &acc_re, + std::vector &acc_im, std::vector &local_used, + std::vector>> &row_values, + std::vector> &row_col_indices) { + std::vector used_cols; + used_cols.reserve(other.cols); + + for (int ja = self.row_ptr[i]; ja < self.row_ptr[i + 1]; ++ja) { + const int ka = self.col_indices[ja]; + const T a_re = self.values[ja].re; + const T a_im = self.values[ja].im; + const int jb_start = other.row_ptr[ka]; + const int jb_end = other.row_ptr[ka + 1]; + + for (int jb = jb_start; jb < jb_end; ++jb) { + const int cb = other.col_indices[jb]; + if (!local_used[cb]) { + local_used[cb] = true; + acc_re[cb] = T(0); + acc_im[cb] = T(0); + used_cols.push_back(cb); + } + acc_re[cb] += (a_re * other.values[jb].re) - (a_im * other.values[jb].im); + acc_im[cb] += (a_re * other.values[jb].im) + (a_im * other.values[jb].re); + } + } + + std::ranges::sort(used_cols); + row_values[i].reserve(used_cols.size()); + row_col_indices[i].reserve(used_cols.size()); + + for (const int c : used_cols) { + row_values[i].emplace_back(acc_re[c], acc_im[c]); + row_col_indices[i].push_back(c); + local_used[c] = false; + } + } + + public: + [[nodiscard]] CSRMatrix OMPMultiply(const CSRMatrix &other) const { + if (cols != other.rows) { + return {}; + } + + CSRMatrix result(rows, other.cols); + std::vector>> row_values(rows); + std::vector> row_col_indices(rows); + + const CSRMatrix &self = *this; + const int nrows = rows; + const int ncols = other.cols; + +#pragma omp parallel default(none) shared(self, other, row_values, row_col_indices, nrows, ncols) + { + std::vector acc_re(static_cast(ncols)); + std::vector acc_im(static_cast(ncols)); + std::vector local_used(static_cast(ncols), false); + +#pragma omp for schedule(dynamic) + for (int i = 0; i < nrows; ++i) { + ProcessRow(i, self, other, acc_re, acc_im, local_used, row_values, row_col_indices); + } + } + + int total_nnz = 0; + for (int i = 0; i < rows; ++i) { + total_nnz += static_cast(row_values[i].size()); + } + + result.values.reserve(static_cast(total_nnz)); + result.col_indices.reserve(static_cast(total_nnz)); + + for (int i = 0; i < rows; ++i) { + result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); + result.col_indices.insert(result.col_indices.end(), row_col_indices[i].begin(), row_col_indices[i].end()); + result.row_ptr[i + 1] = static_cast(result.values.size()); + } + + return result; + } + [[nodiscard]] std::vector> ToDense() const { std::vector> dense(rows * cols); for (int i = 0; i < rows; ++i) { From c13076d104cdd0cf509e7785acd64ea73a249581 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Tue, 14 Apr 2026 13:10:21 +0300 Subject: [PATCH 19/33] implement stl --- tasks/example_threads/stl/report.md | 0 .../common/include/common.hpp | 84 +++++++++- .../stl/include/ops_stl.hpp | 22 +++ .../stl/src/ops_stl.cpp | 155 ++++++++++++++++++ .../tbb/src/ops_tbb.cpp | 140 +++++++++------- .../tests/functional/main.cpp | 6 +- .../tests/performance/main.cpp | 6 +- 7 files changed, 353 insertions(+), 60 deletions(-) delete mode 100644 tasks/example_threads/stl/report.md create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp diff --git a/tasks/example_threads/stl/report.md b/tasks/example_threads/stl/report.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp index 9b407ba0c..b04b0edf7 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -131,6 +131,88 @@ class CSRMatrix { return result; } + private: + static void ProcessRow(int i, const CSRMatrix &self, const CSRMatrix &other, std::vector &acc_re, + std::vector &acc_im, std::vector &local_used, + std::vector>> &row_values, + std::vector> &row_col_indices) { + std::vector used_cols; + used_cols.reserve(other.cols); + + for (int ja = self.row_ptr[i]; ja < self.row_ptr[i + 1]; ++ja) { + const int ka = self.col_indices[ja]; + const T a_re = self.values[ja].re; + const T a_im = self.values[ja].im; + const int jb_start = other.row_ptr[ka]; + const int jb_end = other.row_ptr[ka + 1]; + + for (int jb = jb_start; jb < jb_end; ++jb) { + const int cb = other.col_indices[jb]; + if (!local_used[cb]) { + local_used[cb] = true; + acc_re[cb] = T(0); + acc_im[cb] = T(0); + used_cols.push_back(cb); + } + acc_re[cb] += (a_re * other.values[jb].re) - (a_im * other.values[jb].im); + acc_im[cb] += (a_re * other.values[jb].im) + (a_im * other.values[jb].re); + } + } + + std::ranges::sort(used_cols); + row_values[i].reserve(used_cols.size()); + row_col_indices[i].reserve(used_cols.size()); + + for (const int c : used_cols) { + row_values[i].emplace_back(acc_re[c], acc_im[c]); + row_col_indices[i].push_back(c); + local_used[c] = false; + } + } + + public: + [[nodiscard]] CSRMatrix OMPMultiply(const CSRMatrix &other) const { + if (cols != other.rows) { + return {}; + } + + CSRMatrix result(rows, other.cols); + std::vector>> row_values(rows); + std::vector> row_col_indices(rows); + + const CSRMatrix &self = *this; + const int nrows = rows; + const int ncols = other.cols; + +#pragma omp parallel default(none) shared(self, other, row_values, row_col_indices, nrows, ncols) + { + std::vector acc_re(static_cast(ncols)); + std::vector acc_im(static_cast(ncols)); + std::vector local_used(static_cast(ncols), false); + +#pragma omp for schedule(dynamic) + for (int i = 0; i < nrows; ++i) { + ProcessRow(i, self, other, acc_re, acc_im, local_used, row_values, row_col_indices); + } + } + + int total_nnz = 0; + for (int i = 0; i < rows; ++i) { + total_nnz += static_cast(row_values[i].size()); + } + + result.values.reserve(static_cast(total_nnz)); + result.col_indices.reserve(static_cast(total_nnz)); + + for (int i = 0; i < rows; ++i) { + result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); + result.col_indices.insert(result.col_indices.end(), row_col_indices[i].begin(), row_col_indices[i].end()); + result.row_ptr[i + 1] = static_cast(result.values.size()); + } + + return result; + } + [[nodiscard]] std::vector> ToDense() const { std::vector> dense(rows * cols); for (int i = 0; i < rows; ++i) { @@ -149,4 +231,4 @@ using OutType = SparseMatrix; using TestType = std::tuple; using BaseTask = ppc::task::Task; -} // namespace kurpiakov_a_sp_comp_mat_mul +} // namespace kurpiakov_a_sp_comp_mat_mul \ No newline at end of file diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp new file mode 100644 index 000000000..8531d8d87 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiakovACRSMatMulSTL : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSTL; + } + explicit KurpiakovACRSMatMulSTL(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp new file mode 100644 index 000000000..88e8daeed --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp @@ -0,0 +1,155 @@ +#include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" + +#include +#include +#include +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +namespace { + +bool ValidateCSR(const SparseMatrix &m) { + if (m.rows <= 0 || m.cols <= 0) { + return false; + } + if (static_cast(m.row_ptr.size()) != m.rows + 1) { + return false; + } + if (m.row_ptr[0] != 0) { + return false; + } + if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) { + return false; + } + if (m.col_indices.size() != m.values.size()) { + return false; + } + for (int i = 0; i < m.rows; ++i) { + for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) { + if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) { + return false; + } + } + } + return true; +} + +} // namespace + +KurpiakovACRSMatMulSTL::KurpiakovACRSMatMulSTL(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulSTL::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulSTL::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulSTL::RunImpl() { + const auto &[a, b] = GetInput(); + const int rows = a.rows; + const int cols = b.cols; + + const int requested_threads = ppc::util::GetNumThreads(); + const int num_threads = std::max(1, std::min(requested_threads, rows)); + + std::vector> row_values(rows); + std::vector> row_cols(rows); + + std::atomic next_row(0); + std::vector threads; + threads.reserve(num_threads); + + for (int t = 0; t < num_threads; ++t) { + threads.emplace_back([&]() { + std::vector row_acc(cols); + std::vector row_used(cols, 0); + std::vector used_cols; + + while (true) { + const int i = next_row.fetch_add(1, std::memory_order_relaxed); + if (i >= rows) { + break; + } + + used_cols.clear(); + + for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; + + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; + + if (row_used[cb] == 0) { + row_used[cb] = 1; + row_acc[cb] = ComplexD(); + used_cols.push_back(cb); + } + row_acc[cb] += a_val * b_val; + } + } + + std::sort(used_cols.begin(), used_cols.end()); + + auto ¤t_row_values = row_values[i]; + auto ¤t_row_cols = row_cols[i]; + current_row_values.clear(); + current_row_cols.clear(); + current_row_values.reserve(used_cols.size()); + current_row_cols.reserve(used_cols.size()); + + for (int c : used_cols) { + current_row_values.push_back(row_acc[c]); + current_row_cols.push_back(c); + row_used[c] = 0; + } + } + }); + } + + for (auto &thread : threads) { + thread.join(); + } + + SparseMatrix result(rows, cols); + std::size_t total_nnz = 0; + for (int i = 0; i < rows; ++i) { + total_nnz += row_values[i].size(); + } + + result.values.reserve(total_nnz); + result.col_indices.reserve(total_nnz); + + for (int i = 0; i < rows; ++i) { + result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); + result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); + result.row_ptr[i + 1] = static_cast(result.values.size()); + } + + GetOutput() = std::move(result); + return true; +} + +bool KurpiakovACRSMatMulSTL::PostProcessingImpl() { + return true; +} + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp index 2a802a620..121f9dd99 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp @@ -39,6 +39,87 @@ bool ValidateCSR(const SparseMatrix &m) { return true; } +void MultiplyRowIntoBuffers(const SparseMatrix &a, const SparseMatrix &b, int row_idx, std::vector &row_acc, + std::vector &row_used, std::vector &used_cols, + std::vector ¤t_row_values, std::vector ¤t_row_cols) { + used_cols.clear(); + + for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; + + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; + + if (row_used[cb] == 0) { + row_used[cb] = 1; + row_acc[cb] = ComplexD(); + used_cols.push_back(cb); + } + row_acc[cb] += a_val * b_val; + } + } + + std::ranges::sort(used_cols); + + current_row_values.clear(); + current_row_cols.clear(); + current_row_values.reserve(used_cols.size()); + current_row_cols.reserve(used_cols.size()); + + for (int c : used_cols) { + current_row_values.push_back(row_acc[c]); + current_row_cols.push_back(c); + row_used[c] = 0; + } +} + +class TbbRowsMultiplierBody { + public: + TbbRowsMultiplierBody(const SparseMatrix &a, const SparseMatrix &b, std::vector> &row_values, + std::vector> &row_cols, int cols) + : a_(a), b_(b), row_values_(row_values), row_cols_(row_cols), cols_(cols) {} + + void operator()(const tbb::blocked_range &range) const { + std::vector row_acc(cols_); + std::vector row_used(cols_, 0); + std::vector used_cols; + + for (int i = range.begin(); i < range.end(); ++i) { + MultiplyRowIntoBuffers(a_, b_, i, row_acc, row_used, used_cols, row_values_[i], row_cols_[i]); + } + } + + private: + const SparseMatrix &a_; + const SparseMatrix &b_; + std::vector> &row_values_; + std::vector> &row_cols_; + int cols_; +}; + +SparseMatrix BuildResultFromRows(int rows, int cols, const std::vector> &row_values, + const std::vector> &row_cols) { + SparseMatrix result(rows, cols); + + std::size_t total_nnz = 0; + for (int i = 0; i < rows; ++i) { + total_nnz += row_values[i].size(); + } + + result.values.reserve(total_nnz); + result.col_indices.reserve(total_nnz); + + for (int i = 0; i < rows; ++i) { + result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); + result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); + result.row_ptr[i + 1] = static_cast(result.values.size()); + } + + return result; +} + } // namespace KurpiakovACRSMatMulTBB::KurpiakovACRSMatMulTBB(const InType &in) { @@ -69,64 +150,9 @@ bool KurpiakovACRSMatMulTBB::RunImpl() { std::vector> row_values(rows); std::vector> row_cols(rows); - tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { - std::vector row_acc(cols); - std::vector row_used(cols, 0); - std::vector used_cols; - - for (int i = range.begin(); i < range.end(); ++i) { - used_cols.clear(); - - for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { - const int ka = a.col_indices[ja]; - const ComplexD &a_val = a.values[ja]; - - for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { - const int cb = b.col_indices[jb]; - const ComplexD &b_val = b.values[jb]; - - if (row_used[cb] == 0) { - row_used[cb] = 1; - row_acc[cb] = ComplexD(); - used_cols.push_back(cb); - } - row_acc[cb] += a_val * b_val; - } - } - - std::ranges::sort(used_cols); - - auto ¤t_row_values = row_values[i]; - auto ¤t_row_cols = row_cols[i]; - current_row_values.clear(); - current_row_cols.clear(); - current_row_values.reserve(used_cols.size()); - current_row_cols.reserve(used_cols.size()); - - for (int c : used_cols) { - current_row_values.push_back(row_acc[c]); - current_row_cols.push_back(c); - row_used[c] = 0; - } - } - }); - - SparseMatrix result(rows, cols); - std::size_t total_nnz = 0; - for (int i = 0; i < rows; ++i) { - total_nnz += row_values[i].size(); - } - - result.values.reserve(total_nnz); - result.col_indices.reserve(total_nnz); - - for (int i = 0; i < rows; ++i) { - result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); - result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); - result.row_ptr[i + 1] = static_cast(result.values.size()); - } + tbb::parallel_for(tbb::blocked_range(0, rows), TbbRowsMultiplierBody(a, b, row_values, row_cols, cols)); - GetOutput() = std::move(result); + GetOutput() = BuildResultFromRows(rows, cols, row_values, row_cols); return true; } diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index 094d1ae05..eca12a558 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -6,7 +6,10 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" @@ -148,7 +151,8 @@ TEST_P(KurpiakovRunFuncTestsThreads, SparseMatMulFromParams) { const auto kTestTasksList = std::tuple_cat( ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); const auto kPerfTestName = KurpiakovRunFuncTestsThreads::PrintFuncTestName; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index aa1fb8504..9ebbf15ea 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -4,8 +4,12 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" #include "util/include/perf_test_util.hpp" +#include "util/include/util.hpp" namespace kurpiakov_a_sp_comp_mat_mul { @@ -65,7 +69,7 @@ TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { namespace { const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks( + ppc::util::MakeAllPerfTasks( PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 7c9325db44e96d97c80889d2d5a40857d4d62cbb Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:15:12 +0300 Subject: [PATCH 20/33] Update ops_tbb.cpp --- .../tbb/src/ops_tbb.cpp | 126 ++++++++++-------- 1 file changed, 73 insertions(+), 53 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp index 2a802a620..b2822049e 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp @@ -39,6 +39,74 @@ bool ValidateCSR(const SparseMatrix &m) { return true; } +struct ThreadLocalRowBuffers { + explicit ThreadLocalRowBuffers(int cols) : row_acc(cols), row_used(cols, 0) {} + + std::vector row_acc; + std::vector row_used; + std::vector used_cols; +}; + +void ComputeRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, ThreadLocalRowBuffers &buffers, + std::vector &out_values, std::vector &out_cols) { + buffers.used_cols.clear(); + + for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; + + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; + + if (buffers.row_used[cb] == 0) { + buffers.row_used[cb] = 1; + buffers.row_acc[cb] = ComplexD(); + buffers.used_cols.push_back(cb); + } + + buffers.row_acc[cb] += a_val * b_val; + } + } + + std::ranges::sort(buffers.used_cols); + + out_values.clear(); + out_cols.clear(); + out_values.reserve(buffers.used_cols.size()); + out_cols.reserve(buffers.used_cols.size()); + + for (int c : buffers.used_cols) { + out_values.push_back(buffers.row_acc[c]); + out_cols.push_back(c); + buffers.row_used[c] = 0; + } +} + +SparseMatrix BuildResultFromRows(int rows, int cols, const std::vector> &row_values, + const std::vector> &row_cols) { + SparseMatrix result(rows, cols); + + for (int i = 0; i < rows; ++i) { + result.row_ptr[i + 1] = result.row_ptr[i] + static_cast(row_values[i].size()); + } + + const auto total_nnz = static_cast(result.row_ptr[rows]); + + result.values.resize(total_nnz); + result.col_indices.resize(total_nnz); + + tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { + for (int i = range.begin(); i < range.end(); ++i) { + const auto offset = static_cast::difference_type>(result.row_ptr[i]); + std::copy(row_values[i].begin(), row_values[i].end(), result.values.begin() + offset); + std::copy(row_cols[i].begin(), row_cols[i].end(), result.col_indices.begin() + offset); + } + }); + + return result; +} + } // namespace KurpiakovACRSMatMulTBB::KurpiakovACRSMatMulTBB(const InType &in) { @@ -69,64 +137,16 @@ bool KurpiakovACRSMatMulTBB::RunImpl() { std::vector> row_values(rows); std::vector> row_cols(rows); - tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { - std::vector row_acc(cols); - std::vector row_used(cols, 0); - std::vector used_cols; + tbb::enumerable_thread_specific tls_buffers([&] { return ThreadLocalRowBuffers(cols); }); + tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { + auto &buffers = tls_buffers.local(); for (int i = range.begin(); i < range.end(); ++i) { - used_cols.clear(); - - for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { - const int ka = a.col_indices[ja]; - const ComplexD &a_val = a.values[ja]; - - for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { - const int cb = b.col_indices[jb]; - const ComplexD &b_val = b.values[jb]; - - if (row_used[cb] == 0) { - row_used[cb] = 1; - row_acc[cb] = ComplexD(); - used_cols.push_back(cb); - } - row_acc[cb] += a_val * b_val; - } - } - - std::ranges::sort(used_cols); - - auto ¤t_row_values = row_values[i]; - auto ¤t_row_cols = row_cols[i]; - current_row_values.clear(); - current_row_cols.clear(); - current_row_values.reserve(used_cols.size()); - current_row_cols.reserve(used_cols.size()); - - for (int c : used_cols) { - current_row_values.push_back(row_acc[c]); - current_row_cols.push_back(c); - row_used[c] = 0; - } + ComputeRow(a, b, i, buffers, row_values[i], row_cols[i]); } }); - SparseMatrix result(rows, cols); - std::size_t total_nnz = 0; - for (int i = 0; i < rows; ++i) { - total_nnz += row_values[i].size(); - } - - result.values.reserve(total_nnz); - result.col_indices.reserve(total_nnz); - - for (int i = 0; i < rows; ++i) { - result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); - result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); - result.row_ptr[i + 1] = static_cast(result.values.size()); - } - - GetOutput() = std::move(result); + GetOutput() = BuildResultFromRows(rows, cols, row_values, row_cols); return true; } From 27e83f819e71e777dc608b9e8c25be04d3095a10 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Tue, 14 Apr 2026 13:15:26 +0300 Subject: [PATCH 21/33] Changes to be committed: modified: tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp --- .../tbb/src/ops_tbb.cpp | 98 +++++++++---------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp index 121f9dd99..b2822049e 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp @@ -39,10 +39,17 @@ bool ValidateCSR(const SparseMatrix &m) { return true; } -void MultiplyRowIntoBuffers(const SparseMatrix &a, const SparseMatrix &b, int row_idx, std::vector &row_acc, - std::vector &row_used, std::vector &used_cols, - std::vector ¤t_row_values, std::vector ¤t_row_cols) { - used_cols.clear(); +struct ThreadLocalRowBuffers { + explicit ThreadLocalRowBuffers(int cols) : row_acc(cols), row_used(cols, 0) {} + + std::vector row_acc; + std::vector row_used; + std::vector used_cols; +}; + +void ComputeRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, ThreadLocalRowBuffers &buffers, + std::vector &out_values, std::vector &out_cols) { + buffers.used_cols.clear(); for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { const int ka = a.col_indices[ja]; @@ -52,70 +59,50 @@ void MultiplyRowIntoBuffers(const SparseMatrix &a, const SparseMatrix &b, int ro const int cb = b.col_indices[jb]; const ComplexD &b_val = b.values[jb]; - if (row_used[cb] == 0) { - row_used[cb] = 1; - row_acc[cb] = ComplexD(); - used_cols.push_back(cb); + if (buffers.row_used[cb] == 0) { + buffers.row_used[cb] = 1; + buffers.row_acc[cb] = ComplexD(); + buffers.used_cols.push_back(cb); } - row_acc[cb] += a_val * b_val; + + buffers.row_acc[cb] += a_val * b_val; } } - std::ranges::sort(used_cols); + std::ranges::sort(buffers.used_cols); - current_row_values.clear(); - current_row_cols.clear(); - current_row_values.reserve(used_cols.size()); - current_row_cols.reserve(used_cols.size()); + out_values.clear(); + out_cols.clear(); + out_values.reserve(buffers.used_cols.size()); + out_cols.reserve(buffers.used_cols.size()); - for (int c : used_cols) { - current_row_values.push_back(row_acc[c]); - current_row_cols.push_back(c); - row_used[c] = 0; + for (int c : buffers.used_cols) { + out_values.push_back(buffers.row_acc[c]); + out_cols.push_back(c); + buffers.row_used[c] = 0; } } -class TbbRowsMultiplierBody { - public: - TbbRowsMultiplierBody(const SparseMatrix &a, const SparseMatrix &b, std::vector> &row_values, - std::vector> &row_cols, int cols) - : a_(a), b_(b), row_values_(row_values), row_cols_(row_cols), cols_(cols) {} - - void operator()(const tbb::blocked_range &range) const { - std::vector row_acc(cols_); - std::vector row_used(cols_, 0); - std::vector used_cols; - - for (int i = range.begin(); i < range.end(); ++i) { - MultiplyRowIntoBuffers(a_, b_, i, row_acc, row_used, used_cols, row_values_[i], row_cols_[i]); - } - } - - private: - const SparseMatrix &a_; - const SparseMatrix &b_; - std::vector> &row_values_; - std::vector> &row_cols_; - int cols_; -}; - SparseMatrix BuildResultFromRows(int rows, int cols, const std::vector> &row_values, const std::vector> &row_cols) { SparseMatrix result(rows, cols); - std::size_t total_nnz = 0; for (int i = 0; i < rows; ++i) { - total_nnz += row_values[i].size(); + result.row_ptr[i + 1] = result.row_ptr[i] + static_cast(row_values[i].size()); } - result.values.reserve(total_nnz); - result.col_indices.reserve(total_nnz); + const auto total_nnz = static_cast(result.row_ptr[rows]); - for (int i = 0; i < rows; ++i) { - result.values.insert(result.values.end(), row_values[i].begin(), row_values[i].end()); - result.col_indices.insert(result.col_indices.end(), row_cols[i].begin(), row_cols[i].end()); - result.row_ptr[i + 1] = static_cast(result.values.size()); - } + result.values.resize(total_nnz); + result.col_indices.resize(total_nnz); + + tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { + for (int i = range.begin(); i < range.end(); ++i) { + const auto offset = static_cast::difference_type>(result.row_ptr[i]); + std::copy(row_values[i].begin(), row_values[i].end(), result.values.begin() + offset); + std::copy(row_cols[i].begin(), row_cols[i].end(), result.col_indices.begin() + offset); + } + }); return result; } @@ -150,7 +137,14 @@ bool KurpiakovACRSMatMulTBB::RunImpl() { std::vector> row_values(rows); std::vector> row_cols(rows); - tbb::parallel_for(tbb::blocked_range(0, rows), TbbRowsMultiplierBody(a, b, row_values, row_cols, cols)); + tbb::enumerable_thread_specific tls_buffers([&] { return ThreadLocalRowBuffers(cols); }); + + tbb::parallel_for(tbb::blocked_range(0, rows), [&](const tbb::blocked_range &range) { + auto &buffers = tls_buffers.local(); + for (int i = range.begin(); i < range.end(); ++i) { + ComputeRow(a, b, i, buffers, row_values[i], row_cols[i]); + } + }); GetOutput() = BuildResultFromRows(rows, cols, row_values, row_cols); return true; From 4c46cab7aa248c18a8b814f202a67f3ccf4d18cd Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Tue, 14 Apr 2026 13:16:10 +0300 Subject: [PATCH 22/33] Changes to be committed: modified: tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp modified: tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp | 2 +- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp index b04b0edf7..3dc8f9511 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp @@ -231,4 +231,4 @@ using OutType = SparseMatrix; using TestType = std::tuple; using BaseTask = ppc::task::Task; -} // namespace kurpiakov_a_sp_comp_mat_mul \ No newline at end of file +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 9ebbf15ea..14a4e6ce9 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -69,8 +69,8 @@ TEST_P(KurpiakovRunPerfTests, SparseMatMulPerf) { namespace { const auto kAllPerfTasks = - ppc::util::MakeAllPerfTasks( - PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); + ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 775cf261f049a309c6f82032372a5bcd0650b358 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:51:08 +0300 Subject: [PATCH 23/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 14a4e6ce9..509d63706 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -70,7 +70,7 @@ namespace { const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); + KurpiakovACRSMatMulALL>(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 10c934640f81b9c92f4e17e678337816c696492b Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:08:40 +0300 Subject: [PATCH 24/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 509d63706..6b64642cc 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -70,7 +70,7 @@ namespace { const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); + KurpiakovACRSMatMulSTL>(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 67232e4851871750673253f653b09bf21b2eb02a Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Tue, 14 Apr 2026 15:00:18 +0300 Subject: [PATCH 25/33] implement stl+mpi version --- .../all/include/ops_all.hpp | 22 ++ .../all/src/ops_all.cpp | 247 ++++++++++++++++++ .../tests/functional/main.cpp | 4 +- .../tests/performance/main.cpp | 3 +- 4 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp create mode 100644 tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp b/tasks/kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp new file mode 100644 index 000000000..41a24cc06 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +class KurpiakovACRSMatMulALL : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kALL; + } + explicit KurpiakovACRSMatMulALL(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp new file mode 100644 index 000000000..7d9312f87 --- /dev/null +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp @@ -0,0 +1,247 @@ +#include "kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp" + +#include + +#include +#include +#include +#include +#include + +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace kurpiakov_a_sp_comp_mat_mul { + +namespace { + +bool ValidateCSR(const SparseMatrix &m) { + if (m.rows <= 0 || m.cols <= 0) { + return false; + } + if (static_cast(m.row_ptr.size()) != m.rows + 1) { + return false; + } + if (m.row_ptr[0] != 0) { + return false; + } + if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) { + return false; + } + if (m.col_indices.size() != m.values.size()) { + return false; + } + for (int i = 0; i < m.rows; ++i) { + for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) { + if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) { + return false; + } + } + } + return true; +} + +std::pair GetRowRange(int total_rows, int rank, int size) { + const int begin = (total_rows * rank) / size; + const int end = (total_rows * (rank + 1)) / size; + return {begin, end}; +} + +void MultiplySingleRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, std::vector &row_acc, + std::vector &row_used, std::vector &used_cols, std::vector &out_values, + std::vector &out_cols) { + used_cols.clear(); + + for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; + + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; + + if (row_used[cb] == 0) { + row_used[cb] = 1; + row_acc[cb] = ComplexD(); + used_cols.push_back(cb); + } + + row_acc[cb] += a_val * b_val; + } + } + + std::sort(used_cols.begin(), used_cols.end()); + + out_values.clear(); + out_cols.clear(); + out_values.reserve(used_cols.size()); + out_cols.reserve(used_cols.size()); + + for (int col : used_cols) { + out_values.push_back(row_acc[col]); + out_cols.push_back(col); + row_used[col] = 0; + } +} + +void ComputeLocalRowsThreads(const SparseMatrix &a, const SparseMatrix &b, int row_begin, int row_end, + std::vector> &local_values, + std::vector> &local_cols) { + const int local_rows = row_end - row_begin; + const int requested_threads = ppc::util::GetNumThreads(); + const int max_threads = std::max(1, local_rows); + const int num_threads = std::max(1, std::min(requested_threads, max_threads)); + + std::atomic next_row(row_begin); + std::vector workers; + workers.reserve(num_threads); + + for (int t = 0; t < num_threads; ++t) { + workers.emplace_back([&]() { + std::vector row_acc(b.cols); + std::vector row_used(b.cols, 0); + std::vector used_cols; + + while (true) { + const int row = next_row.fetch_add(1, std::memory_order_relaxed); + if (row >= row_end) { + break; + } + + const int local_idx = row - row_begin; + MultiplySingleRow(a, b, row, row_acc, row_used, used_cols, local_values[local_idx], local_cols[local_idx]); + } + }); + } + + for (auto &worker : workers) { + worker.join(); + } +} + +} // namespace + +KurpiakovACRSMatMulALL::KurpiakovACRSMatMulALL(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulALL::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulALL::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulALL::RunImpl() { + const auto &[a, b] = GetInput(); + const int rows = a.rows; + const int cols = b.cols; + + int rank = 0; + int world_size = 1; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + const auto [row_begin, row_end] = GetRowRange(rows, rank, world_size); + const int local_rows = row_end - row_begin; + + std::vector> local_values(local_rows); + std::vector> local_cols(local_rows); + + ComputeLocalRowsThreads(a, b, row_begin, row_end, local_values, local_cols); + + std::vector local_row_nnz(rows, 0); + for (int local_i = 0; local_i < local_rows; ++local_i) { + local_row_nnz[row_begin + local_i] = static_cast(local_values[local_i].size()); + } + + std::vector global_row_nnz(rows, 0); + MPI_Allreduce(local_row_nnz.data(), global_row_nnz.data(), rows, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + + std::vector global_row_ptr(rows + 1, 0); + for (int i = 0; i < rows; ++i) { + global_row_ptr[i + 1] = global_row_ptr[i] + global_row_nnz[i]; + } + + const int total_nnz = global_row_ptr[rows]; + const int local_nnz = global_row_ptr[row_end] - global_row_ptr[row_begin]; + + std::vector local_re(local_nnz); + std::vector local_im(local_nnz); + std::vector local_col_indices(local_nnz); + + int pos = 0; + for (int local_i = 0; local_i < local_rows; ++local_i) { + const auto &vals = local_values[local_i]; + const auto &cols_row = local_cols[local_i]; + + for (std::size_t j = 0; j < vals.size(); ++j) { + local_re[pos] = vals[j].re; + local_im[pos] = vals[j].im; + local_col_indices[pos] = cols_row[j]; + ++pos; + } + } + + std::vector recv_counts(world_size, 0); + MPI_Allgather(&local_nnz, 1, MPI_INT, recv_counts.data(), 1, MPI_INT, MPI_COMM_WORLD); + + std::vector recv_displs(world_size, 0); + for (int r = 1; r < world_size; ++r) { + recv_displs[r] = recv_displs[r - 1] + recv_counts[r - 1]; + } + + std::vector global_re; + std::vector global_im; + std::vector global_col_indices; + + if (rank == 0) { + global_re.resize(total_nnz); + global_im.resize(total_nnz); + global_col_indices.resize(total_nnz); + } + + MPI_Gatherv(local_re.data(), local_nnz, MPI_DOUBLE, global_re.data(), recv_counts.data(), recv_displs.data(), + MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Gatherv(local_im.data(), local_nnz, MPI_DOUBLE, global_im.data(), recv_counts.data(), recv_displs.data(), + MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Gatherv(local_col_indices.data(), local_nnz, MPI_INT, global_col_indices.data(), recv_counts.data(), + recv_displs.data(), MPI_INT, 0, MPI_COMM_WORLD); + + if (rank != 0) { + global_re.resize(total_nnz); + global_im.resize(total_nnz); + global_col_indices.resize(total_nnz); + } + + MPI_Bcast(global_re.data(), total_nnz, MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Bcast(global_im.data(), total_nnz, MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Bcast(global_col_indices.data(), total_nnz, MPI_INT, 0, MPI_COMM_WORLD); + + SparseMatrix result(rows, cols); + result.row_ptr = std::move(global_row_ptr); + result.col_indices = std::move(global_col_indices); + result.values.resize(static_cast(total_nnz)); + + for (int i = 0; i < total_nnz; ++i) { + result.values[static_cast(i)] = ComplexD(global_re[i], global_im[i]); + } + + GetOutput() = std::move(result); + return true; +} + +bool KurpiakovACRSMatMulALL::PostProcessingImpl() { + return true; +} + +} // namespace kurpiakov_a_sp_comp_mat_mul diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index eca12a558..b31aabb3d 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -6,6 +6,7 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp" #include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" #include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" @@ -152,7 +153,8 @@ const auto kTestTasksList = std::tuple_cat( ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), - ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul), + ppc::util::AddFuncTask(kTestParam, PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); const auto kPerfTestName = KurpiakovRunFuncTestsThreads::PrintFuncTestName; diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 14a4e6ce9..ceb486aad 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -4,6 +4,7 @@ #include #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp" #include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" #include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" @@ -70,7 +71,7 @@ namespace { const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); + KurpiakovACRSMatMulSTL, KurpiakovACRSMatMulALL>(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 74d5fc7a61391a28630766d133de53fa59d0fe4f Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:17:08 +0300 Subject: [PATCH 26/33] Update ops_stl.cpp --- .../stl/src/ops_stl.cpp | 159 ++++++++++-------- 1 file changed, 90 insertions(+), 69 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp index 88e8daeed..120fdcfc4 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -39,97 +40,80 @@ bool ValidateCSR(const SparseMatrix &m) { return true; } -} // namespace +struct ThreadLocalRowState { + explicit ThreadLocalRowState(int cols) : row_acc(cols), row_used(cols, 0) {} -KurpiakovACRSMatMulSTL::KurpiakovACRSMatMulSTL(const InType &in) { - SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = SparseMatrix(); -} + std::vector row_acc; + std::vector row_used; + std::vector used_cols; +}; -bool KurpiakovACRSMatMulSTL::ValidationImpl() { - const auto &[a, b] = GetInput(); +void MultiplySingleRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, ThreadLocalRowState &state, + std::vector &out_values, std::vector &out_cols) { + state.used_cols.clear(); - if (!ValidateCSR(a) || !ValidateCSR(b)) { - return false; - } + for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; - return a.cols == b.rows; -} + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; -bool KurpiakovACRSMatMulSTL::PreProcessingImpl() { - return true; -} + if (state.row_used[cb] == 0) { + state.row_used[cb] = 1; + state.row_acc[cb] = ComplexD(); + state.used_cols.push_back(cb); + } -bool KurpiakovACRSMatMulSTL::RunImpl() { - const auto &[a, b] = GetInput(); - const int rows = a.rows; - const int cols = b.cols; + state.row_acc[cb] += a_val * b_val; + } + } - const int requested_threads = ppc::util::GetNumThreads(); - const int num_threads = std::max(1, std::min(requested_threads, rows)); + std::ranges::sort(state.used_cols); - std::vector> row_values(rows); - std::vector> row_cols(rows); + out_values.clear(); + out_cols.clear(); + out_values.reserve(state.used_cols.size()); + out_cols.reserve(state.used_cols.size()); + for (int col : state.used_cols) { + out_values.push_back(state.row_acc[col]); + out_cols.push_back(col); + state.row_used[col] = 0; + } +} + +void ComputeRowsWithThreads(const SparseMatrix &a, const SparseMatrix &b, int rows, int num_threads, + std::vector> &row_values, std::vector> &row_cols) { std::atomic next_row(0); - std::vector threads; - threads.reserve(num_threads); + std::vector workers; + workers.reserve(num_threads); - for (int t = 0; t < num_threads; ++t) { - threads.emplace_back([&]() { - std::vector row_acc(cols); - std::vector row_used(cols, 0); - std::vector used_cols; + for (int thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + workers.emplace_back([&]() { + ThreadLocalRowState state(b.cols); while (true) { - const int i = next_row.fetch_add(1, std::memory_order_relaxed); - if (i >= rows) { + const int row_idx = next_row.fetch_add(1, std::memory_order_relaxed); + if (row_idx >= rows) { break; } - used_cols.clear(); - - for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { - const int ka = a.col_indices[ja]; - const ComplexD &a_val = a.values[ja]; - - for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { - const int cb = b.col_indices[jb]; - const ComplexD &b_val = b.values[jb]; - - if (row_used[cb] == 0) { - row_used[cb] = 1; - row_acc[cb] = ComplexD(); - used_cols.push_back(cb); - } - row_acc[cb] += a_val * b_val; - } - } - - std::sort(used_cols.begin(), used_cols.end()); - - auto ¤t_row_values = row_values[i]; - auto ¤t_row_cols = row_cols[i]; - current_row_values.clear(); - current_row_cols.clear(); - current_row_values.reserve(used_cols.size()); - current_row_cols.reserve(used_cols.size()); - - for (int c : used_cols) { - current_row_values.push_back(row_acc[c]); - current_row_cols.push_back(c); - row_used[c] = 0; - } + MultiplySingleRow(a, b, row_idx, state, row_values[row_idx], row_cols[row_idx]); } }); } - for (auto &thread : threads) { - thread.join(); + for (auto &worker : workers) { + worker.join(); } +} +SparseMatrix BuildResult(int rows, int cols, const std::vector> &row_values, + const std::vector> &row_cols) { SparseMatrix result(rows, cols); + std::size_t total_nnz = 0; for (int i = 0; i < rows; ++i) { total_nnz += row_values[i].size(); @@ -144,7 +128,44 @@ bool KurpiakovACRSMatMulSTL::RunImpl() { result.row_ptr[i + 1] = static_cast(result.values.size()); } - GetOutput() = std::move(result); + return result; +} + +} // namespace + +KurpiakovACRSMatMulSTL::KurpiakovACRSMatMulSTL(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulSTL::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulSTL::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulSTL::RunImpl() { + const auto &[a, b] = GetInput(); + const int rows = a.rows; + const int cols = b.cols; + + const int requested_threads = ppc::util::GetNumThreads(); + const int num_threads = std::max(1, std::min(requested_threads, rows)); + + std::vector> row_values(rows); + std::vector> row_cols(rows); + + ComputeRowsWithThreads(a, b, rows, num_threads, row_values, row_cols); + GetOutput() = BuildResult(rows, cols, row_values, row_cols); return true; } From 87fc416b637bd8fab5991ea2bb5bc374e787c096 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:17:20 +0300 Subject: [PATCH 27/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 6b64642cc..1ee5502b9 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -9,7 +9,6 @@ #include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" #include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp" #include "util/include/perf_test_util.hpp" -#include "util/include/util.hpp" namespace kurpiakov_a_sp_comp_mat_mul { From 455e2fc88f31be229a9006c9486d8654243a335b Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Tue, 14 Apr 2026 15:21:36 +0300 Subject: [PATCH 28/33] Changes to be committed: modified: tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp --- .../stl/src/ops_stl.cpp | 159 ++++++++++-------- 1 file changed, 90 insertions(+), 69 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp index 88e8daeed..120fdcfc4 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/stl/src/ops_stl.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -39,97 +40,80 @@ bool ValidateCSR(const SparseMatrix &m) { return true; } -} // namespace +struct ThreadLocalRowState { + explicit ThreadLocalRowState(int cols) : row_acc(cols), row_used(cols, 0) {} -KurpiakovACRSMatMulSTL::KurpiakovACRSMatMulSTL(const InType &in) { - SetTypeOfTask(GetStaticTypeOfTask()); - GetInput() = in; - GetOutput() = SparseMatrix(); -} + std::vector row_acc; + std::vector row_used; + std::vector used_cols; +}; -bool KurpiakovACRSMatMulSTL::ValidationImpl() { - const auto &[a, b] = GetInput(); +void MultiplySingleRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, ThreadLocalRowState &state, + std::vector &out_values, std::vector &out_cols) { + state.used_cols.clear(); - if (!ValidateCSR(a) || !ValidateCSR(b)) { - return false; - } + for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) { + const int ka = a.col_indices[ja]; + const ComplexD &a_val = a.values[ja]; - return a.cols == b.rows; -} + for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { + const int cb = b.col_indices[jb]; + const ComplexD &b_val = b.values[jb]; -bool KurpiakovACRSMatMulSTL::PreProcessingImpl() { - return true; -} + if (state.row_used[cb] == 0) { + state.row_used[cb] = 1; + state.row_acc[cb] = ComplexD(); + state.used_cols.push_back(cb); + } -bool KurpiakovACRSMatMulSTL::RunImpl() { - const auto &[a, b] = GetInput(); - const int rows = a.rows; - const int cols = b.cols; + state.row_acc[cb] += a_val * b_val; + } + } - const int requested_threads = ppc::util::GetNumThreads(); - const int num_threads = std::max(1, std::min(requested_threads, rows)); + std::ranges::sort(state.used_cols); - std::vector> row_values(rows); - std::vector> row_cols(rows); + out_values.clear(); + out_cols.clear(); + out_values.reserve(state.used_cols.size()); + out_cols.reserve(state.used_cols.size()); + for (int col : state.used_cols) { + out_values.push_back(state.row_acc[col]); + out_cols.push_back(col); + state.row_used[col] = 0; + } +} + +void ComputeRowsWithThreads(const SparseMatrix &a, const SparseMatrix &b, int rows, int num_threads, + std::vector> &row_values, std::vector> &row_cols) { std::atomic next_row(0); - std::vector threads; - threads.reserve(num_threads); + std::vector workers; + workers.reserve(num_threads); - for (int t = 0; t < num_threads; ++t) { - threads.emplace_back([&]() { - std::vector row_acc(cols); - std::vector row_used(cols, 0); - std::vector used_cols; + for (int thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + workers.emplace_back([&]() { + ThreadLocalRowState state(b.cols); while (true) { - const int i = next_row.fetch_add(1, std::memory_order_relaxed); - if (i >= rows) { + const int row_idx = next_row.fetch_add(1, std::memory_order_relaxed); + if (row_idx >= rows) { break; } - used_cols.clear(); - - for (int ja = a.row_ptr[i]; ja < a.row_ptr[i + 1]; ++ja) { - const int ka = a.col_indices[ja]; - const ComplexD &a_val = a.values[ja]; - - for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) { - const int cb = b.col_indices[jb]; - const ComplexD &b_val = b.values[jb]; - - if (row_used[cb] == 0) { - row_used[cb] = 1; - row_acc[cb] = ComplexD(); - used_cols.push_back(cb); - } - row_acc[cb] += a_val * b_val; - } - } - - std::sort(used_cols.begin(), used_cols.end()); - - auto ¤t_row_values = row_values[i]; - auto ¤t_row_cols = row_cols[i]; - current_row_values.clear(); - current_row_cols.clear(); - current_row_values.reserve(used_cols.size()); - current_row_cols.reserve(used_cols.size()); - - for (int c : used_cols) { - current_row_values.push_back(row_acc[c]); - current_row_cols.push_back(c); - row_used[c] = 0; - } + MultiplySingleRow(a, b, row_idx, state, row_values[row_idx], row_cols[row_idx]); } }); } - for (auto &thread : threads) { - thread.join(); + for (auto &worker : workers) { + worker.join(); } +} +SparseMatrix BuildResult(int rows, int cols, const std::vector> &row_values, + const std::vector> &row_cols) { SparseMatrix result(rows, cols); + std::size_t total_nnz = 0; for (int i = 0; i < rows; ++i) { total_nnz += row_values[i].size(); @@ -144,7 +128,44 @@ bool KurpiakovACRSMatMulSTL::RunImpl() { result.row_ptr[i + 1] = static_cast(result.values.size()); } - GetOutput() = std::move(result); + return result; +} + +} // namespace + +KurpiakovACRSMatMulSTL::KurpiakovACRSMatMulSTL(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = SparseMatrix(); +} + +bool KurpiakovACRSMatMulSTL::ValidationImpl() { + const auto &[a, b] = GetInput(); + + if (!ValidateCSR(a) || !ValidateCSR(b)) { + return false; + } + + return a.cols == b.rows; +} + +bool KurpiakovACRSMatMulSTL::PreProcessingImpl() { + return true; +} + +bool KurpiakovACRSMatMulSTL::RunImpl() { + const auto &[a, b] = GetInput(); + const int rows = a.rows; + const int cols = b.cols; + + const int requested_threads = ppc::util::GetNumThreads(); + const int num_threads = std::max(1, std::min(requested_threads, rows)); + + std::vector> row_values(rows); + std::vector> row_cols(rows); + + ComputeRowsWithThreads(a, b, rows, num_threads, row_values, row_cols); + GetOutput() = BuildResult(rows, cols, row_values, row_cols); return true; } From 66a7637965458ec66e50913c9442b4a64601a028 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:21:48 +0300 Subject: [PATCH 29/33] Update ops_all.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp index 7d9312f87..3ce68ad7b 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp @@ -70,7 +70,7 @@ void MultiplySingleRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx } } - std::sort(used_cols.begin(), used_cols.end()); + std::ranges::sort(used_cols); out_values.clear(); out_cols.clear(); @@ -96,7 +96,7 @@ void ComputeLocalRowsThreads(const SparseMatrix &a, const SparseMatrix &b, int r std::vector workers; workers.reserve(num_threads); - for (int t = 0; t < num_threads; ++t) { + for (int tid = 0; tid < num_threads; ++tid) { workers.emplace_back([&]() { std::vector row_acc(b.cols); std::vector row_used(b.cols, 0); @@ -184,7 +184,7 @@ bool KurpiakovACRSMatMulALL::RunImpl() { const auto &vals = local_values[local_i]; const auto &cols_row = local_cols[local_i]; - for (std::size_t j = 0; j < vals.size(); ++j) { + for (size_t j = 0; j < vals.size(); ++j) { local_re[pos] = vals[j].re; local_im[pos] = vals[j].im; local_col_indices[pos] = cols_row[j]; @@ -196,8 +196,8 @@ bool KurpiakovACRSMatMulALL::RunImpl() { MPI_Allgather(&local_nnz, 1, MPI_INT, recv_counts.data(), 1, MPI_INT, MPI_COMM_WORLD); std::vector recv_displs(world_size, 0); - for (int r = 1; r < world_size; ++r) { - recv_displs[r] = recv_displs[r - 1] + recv_counts[r - 1]; + for (int rec = 1; rec < world_size; ++rec) { + recv_displs[rec] = recv_displs[rec - 1] + recv_counts[rec - 1]; } std::vector global_re; From 23c66d51dfb6229bc419d9df6ea5ad1bc64e39d9 Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:22:09 +0300 Subject: [PATCH 30/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp index b31aabb3d..03862e345 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/functional/main.cpp @@ -5,8 +5,8 @@ #include #include -#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" #include "kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" #include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" #include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" From cdc38bfcff3168f18e30245d586ac850b23a4b4f Mon Sep 17 00:00:00 2001 From: Aleksei Kurpiakov <166383450+AlKurpiakov@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:22:26 +0300 Subject: [PATCH 31/33] Update main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index 1a2d452b9..ad49f7d84 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -3,8 +3,8 @@ #include #include -#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" #include "kurpiakov_a_sp_comp_mat_mul/all/include/ops_all.hpp" +#include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp" #include "kurpiakov_a_sp_comp_mat_mul/omp/include/ops_omp.hpp" #include "kurpiakov_a_sp_comp_mat_mul/seq/include/ops_seq.hpp" #include "kurpiakov_a_sp_comp_mat_mul/stl/include/ops_stl.hpp" From 3466024024667b153d6263c4cdaf30583ee8fb28 Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 16 Apr 2026 19:34:50 +0300 Subject: [PATCH 32/33] Changes to be committed: modified: tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp index ad49f7d84..249bd5cc4 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/tests/performance/main.cpp @@ -70,7 +70,8 @@ namespace { const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks(PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); + KurpiakovACRSMatMulSTL, KurpiakovACRSMatMulALL>( + PPC_SETTINGS_kurpiakov_a_sp_comp_mat_mul); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); const auto kPerfTestName = KurpiakovRunPerfTests::CustomPerfTestName; From 9b09252080a023d1cf4b332447b42132545d3aea Mon Sep 17 00:00:00 2001 From: AlKurpiakov Date: Thu, 16 Apr 2026 20:23:27 +0300 Subject: [PATCH 33/33] Changes to be committed: modified: tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp --- tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp index 3ce68ad7b..2fedadf40 100644 --- a/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp +++ b/tasks/kurpiakov_a_sp_comp_mat_mul/all/src/ops_all.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -230,10 +231,10 @@ bool KurpiakovACRSMatMulALL::RunImpl() { SparseMatrix result(rows, cols); result.row_ptr = std::move(global_row_ptr); result.col_indices = std::move(global_col_indices); - result.values.resize(static_cast(total_nnz)); + result.values.resize(static_cast(total_nnz)); for (int i = 0; i < total_nnz; ++i) { - result.values[static_cast(i)] = ComplexD(global_re[i], global_im[i]); + result.values[static_cast(i)] = ComplexD(global_re[i], global_im[i]); } GetOutput() = std::move(result);