Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"student": {
"first_name": "Дмитрий",
"group_number": "3823Б1ФИ2",
"last_name": "Лобанов",
"middle_name": "Александрович",
"task_number": "1"
}
}
22 changes: 22 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/omp/include/ops_omp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "lobanov_d_multi_matrix_crs/common/include/common.hpp"
#include "task/include/task.hpp"

namespace lobanov_d_multi_matrix_crs {

class LobanovMultyMatrixOMP : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kOMP;
}
explicit LobanovMultyMatrixOMP(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;
};

} // namespace lobanov_d_multi_matrix_crs
113 changes: 113 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/omp/src/ops_omp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "lobanov_d_multi_matrix_crs/omp/include/ops_omp.hpp"

#include <cmath>
#include <cstddef>
#include <map>
#include <vector>

#include "lobanov_d_multi_matrix_crs/common/include/common.hpp"
#include "util/include/util.hpp"

namespace lobanov_d_multi_matrix_crs {

LobanovMultyMatrixOMP::LobanovMultyMatrixOMP(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = CompressedRowMatrix{};
}

bool LobanovMultyMatrixOMP::ValidationImpl() {
const auto &matrix_a = GetInput().first;
const auto &matrix_b = GetInput().second;

if (matrix_a.row_count <= 0 || matrix_b.row_count <= 0 || matrix_a.column_count <= 0 || matrix_b.column_count <= 0) {
return false;
}
if (matrix_a.column_count != matrix_b.row_count) {
return false;
}
if (matrix_a.row_pointer_data.size() != static_cast<size_t>(matrix_a.row_count) + 1 ||
matrix_b.row_pointer_data.size() != static_cast<size_t>(matrix_b.row_count) + 1) {
return false;
}
if (static_cast<size_t>(matrix_a.non_zero_count) != matrix_a.value_data.size() ||
static_cast<size_t>(matrix_a.non_zero_count) != matrix_a.column_index_data.size() ||
static_cast<size_t>(matrix_b.non_zero_count) != matrix_b.value_data.size() ||
static_cast<size_t>(matrix_b.non_zero_count) != matrix_b.column_index_data.size()) {
return false;
}
return true;
}

bool LobanovMultyMatrixOMP::PreProcessingImpl() {
const auto &matrix_a = GetInput().first;
const auto &matrix_b = GetInput().second;

auto &result = GetOutput();
result.row_count = matrix_a.row_count;
result.column_count = matrix_b.column_count;
result.non_zero_count = 0;
result.value_data.clear();
result.column_index_data.clear();
result.row_pointer_data.assign(static_cast<size_t>(result.row_count) + 1, 0);
return true;
}

bool LobanovMultyMatrixOMP::RunImpl() {
const auto &matrix_a = GetInput().first;
const auto &matrix_b = GetInput().second;
auto &result = GetOutput();

const int rows_a = matrix_a.row_count;

std::vector<std::map<int, double>> row_results(static_cast<size_t>(rows_a));

#pragma omp parallel for default(none) shared(matrix_a, matrix_b, row_results, rows_a) \
num_threads(ppc::util::GetNumThreads()) schedule(dynamic)
for (int i = 0; i < rows_a; ++i) {
const int a_start = matrix_a.row_pointer_data[static_cast<size_t>(i)];
const int a_end = matrix_a.row_pointer_data[static_cast<size_t>(i) + 1];

for (int a_idx = a_start; a_idx < a_end; ++a_idx) {
const int k = matrix_a.column_index_data[static_cast<size_t>(a_idx)];
const double a_val = matrix_a.value_data[static_cast<size_t>(a_idx)];

if (k >= matrix_b.row_count) {
continue;
}

const int b_start = matrix_b.row_pointer_data[static_cast<size_t>(k)];
const int b_end = matrix_b.row_pointer_data[static_cast<size_t>(k) + 1];

for (int b_idx = b_start; b_idx < b_end; ++b_idx) {
const int j = matrix_b.column_index_data[static_cast<size_t>(b_idx)];
const double b_val = matrix_b.value_data[static_cast<size_t>(b_idx)];

row_results[static_cast<size_t>(i)][j] += a_val * b_val;
}
}
}

int offset = 0;
result.row_pointer_data[0] = 0;
for (int i = 0; i < rows_a; ++i) {
const auto &row = row_results[static_cast<size_t>(i)];
for (const auto &[col, val] : row) {
if (std::abs(val) > 1e-12) {
result.column_index_data.push_back(col);
result.value_data.push_back(val);
++offset;
}
}
result.row_pointer_data[static_cast<size_t>(i) + 1] = offset;
}
result.non_zero_count = static_cast<int>(result.value_data.size());

return true;
}

bool LobanovMultyMatrixOMP::PostProcessingImpl() {
return true;
}

} // namespace lobanov_d_multi_matrix_crs
Empty file.
25 changes: 25 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/seq/include/ops_seq.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "lobanov_d_multi_matrix_crs/common/include/common.hpp"
#include "task/include/task.hpp"

namespace lobanov_d_multi_matrix_crs {
class LobanovMultyMatrixSEQ : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kSEQ;
}
explicit LobanovMultyMatrixSEQ(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;

static void PerformMatrixMultiplication(const CompressedRowMatrix &first_matrix,
const CompressedRowMatrix &second_matrix,
CompressedRowMatrix &product_result);
};

} // namespace lobanov_d_multi_matrix_crs
Empty file.
143 changes: 143 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/seq/src/ops_seq.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include "lobanov_d_multi_matrix_crs/seq/include/ops_seq.hpp"

#include <cmath>
#include <cstddef>
#include <exception>
#include <vector>

#include "lobanov_d_multi_matrix_crs/common/include/common.hpp"

namespace lobanov_d_multi_matrix_crs {

constexpr double kEpsilonThreshold = 1e-12;

LobanovMultyMatrixSEQ::LobanovMultyMatrixSEQ(const InType &input_matrices) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = input_matrices;
CompressedRowMatrix empty_matrix;
empty_matrix.row_count = 0;
empty_matrix.column_count = 0;
empty_matrix.non_zero_count = 0;
GetOutput() = empty_matrix;
}

bool LobanovMultyMatrixSEQ::ValidationImpl() {
const auto &[matrix_a, matrix_b] = GetInput();
return (matrix_a.row_count > 0 && matrix_a.column_count > 0 && matrix_b.row_count > 0 && matrix_b.column_count > 0 &&
matrix_a.column_count == matrix_b.row_count);
}

bool LobanovMultyMatrixSEQ::PreProcessingImpl() {
return true;
}

namespace {

void MultiplyRowByMatrix(const std::vector<double> &a_row_values, const std::vector<int> &a_row_columns,
const CompressedRowMatrix &matrix_b, std::vector<double> &temp_row,
std::vector<int> &temp_col_markers, int row_index, std::vector<double> &result_values,
std::vector<int> &result_col_indices, int &result_row_start) {
for (size_t i = 0; i < temp_row.size(); ++i) {
if (temp_col_markers[i] == row_index) {
temp_row[i] = 0.0;
temp_col_markers[i] = -1;
}
}

// Умножаем строку A на матрицу B
for (size_t k = 0; k < a_row_columns.size(); ++k) {
int b_row = a_row_columns[k];
double a_value = a_row_values[k];

for (int b_ptr = matrix_b.row_pointer_data[b_row]; b_ptr < matrix_b.row_pointer_data[b_row + 1]; ++b_ptr) {
int b_col = matrix_b.column_index_data[b_ptr];
double b_value = matrix_b.value_data[b_ptr];

if (temp_col_markers[b_col] != row_index) {
temp_col_markers[b_col] = row_index;
temp_row[b_col] = a_value * b_value;
} else {
temp_row[b_col] += a_value * b_value;
}
}
}

for (int col = 0; col < matrix_b.column_count; ++col) {
if (temp_col_markers[col] == row_index && std::abs(temp_row[col]) > kEpsilonThreshold) {
result_values.push_back(temp_row[col]);
result_col_indices.push_back(col);
}
}

result_row_start = static_cast<int>(result_values.size());
}

} // namespace

void LobanovMultyMatrixSEQ::PerformMatrixMultiplication(const CompressedRowMatrix &first_matrix,
const CompressedRowMatrix &second_matrix,
CompressedRowMatrix &product_result) {
product_result.row_count = first_matrix.row_count;
product_result.column_count = second_matrix.column_count;

product_result.row_pointer_data.clear();
product_result.row_pointer_data.push_back(0);

product_result.value_data.clear();
product_result.column_index_data.clear();

int cols = second_matrix.column_count;
std::vector<double> temp_row(cols, 0.0);
std::vector<int> temp_col_markers(cols, -1);

for (int i = 0; i < first_matrix.row_count; ++i) {
int row_start = first_matrix.row_pointer_data[i];
int row_end = first_matrix.row_pointer_data[i + 1];

if (row_start == row_end) {
product_result.row_pointer_data.push_back(static_cast<int>(product_result.value_data.size()));
continue;
}

std::vector<double> a_row_values;
std::vector<int> a_row_columns;

for (int ptr = row_start; ptr < row_end; ++ptr) {
a_row_values.push_back(first_matrix.value_data[ptr]);
a_row_columns.push_back(first_matrix.column_index_data[ptr]);
}

int result_row_start = 0;
MultiplyRowByMatrix(a_row_values, a_row_columns, second_matrix, temp_row, temp_col_markers, i,
product_result.value_data, product_result.column_index_data, result_row_start);

product_result.row_pointer_data.push_back(static_cast<int>(product_result.value_data.size()));
}

product_result.non_zero_count = static_cast<int>(product_result.value_data.size());
}

bool LobanovMultyMatrixSEQ::RunImpl() {
const auto &[matrix_a, matrix_b] = GetInput();

try {
CompressedRowMatrix result_matrix;
result_matrix.row_count = 0;
result_matrix.column_count = 0;
result_matrix.non_zero_count = 0;

PerformMatrixMultiplication(matrix_a, matrix_b, result_matrix);
GetOutput() = result_matrix;
return true;
} catch (const std::exception &) {
return false;
}
}

bool LobanovMultyMatrixSEQ::PostProcessingImpl() {
const auto &result_matrix = GetOutput();
return result_matrix.row_count > 0 && result_matrix.column_count > 0 &&
result_matrix.row_pointer_data.size() == static_cast<size_t>(result_matrix.row_count) + 1;
}

} // namespace lobanov_d_multi_matrix_crs
10 changes: 10 additions & 0 deletions tasks/lobanov_d_multi_matrix_crs/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"tasks": {
"all": "enabled",
"omp": "enabled",
"seq": "enabled",
"stl": "enabled",
"tbb": "enabled"
},
"tasks_type": "threads"
}
Loading
Loading