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
24 changes: 24 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/common/include/common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <string>
#include <tuple>
#include <vector>

#include "task/include/task.hpp"

namespace smyshlaev_a_sle_cg_seq {

using CGVector = std::vector<double>;
using CGMatrix = std::vector<CGVector>;

struct InputType {
CGMatrix A;
CGVector b;
};

using InType = InputType;
using OutType = CGVector;
using TestType = std::tuple<int, std::string>;
using BaseTask = ppc::task::Task<InType, OutType>;

} // namespace smyshlaev_a_sle_cg_seq
9 changes: 9 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/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"
}
}
25 changes: 25 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/seq/include/ops_seq.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <vector>

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

namespace smyshlaev_a_sle_cg_seq {

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

private:
std::vector<double> flat_A_;
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;
};

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

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

#include "smyshlaev_a_sle_cg_seq/common/include/common.hpp"

namespace smyshlaev_a_sle_cg_seq {

namespace {

double ComputeDotProduct(const std::vector<double> &v1, const std::vector<double> &v2) {
double result = 0.0;
size_t n = v1.size();
for (size_t i = 0; i < n; ++i) {
result += v1[i] * v2[i];
}
return result;
}

void ComputeAp(const std::vector<double> &matrix, const std::vector<double> &p, std::vector<double> &ap, size_t n) {
for (size_t i = 0; i < n; ++i) {
double sum = 0.0;
for (size_t j = 0; j < n; ++j) {
sum += matrix[(i * n) + j] * p[j];
}
ap[i] = sum;
}
}

double UpdateResultAndResidual(std::vector<double> &result, std::vector<double> &r, const std::vector<double> &p,
const std::vector<double> &ap, double alpha) {
double rs_new = 0.0;
size_t n = result.size();
for (size_t i = 0; i < n; ++i) {
result[i] += alpha * p[i];
r[i] -= alpha * ap[i];
rs_new += r[i] * r[i];
}
return rs_new;
}

void UpdateP(std::vector<double> &p, const std::vector<double> &r, double beta) {
size_t n = p.size();
for (size_t i = 0; i < n; ++i) {
p[i] = r[i] + (beta * p[i]);
}
}

} // namespace

SmyshlaevASleCgTaskSEQ::SmyshlaevASleCgTaskSEQ(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
}

bool SmyshlaevASleCgTaskSEQ::ValidationImpl() {
const auto &a = GetInput().A;
const auto &b = GetInput().b;
if (a.empty() || b.empty()) {
return false;
}
if (a.size() != b.size()) {
return false;
}
if (a.size() != a[0].size()) {
return false;
}
return true;
}

bool SmyshlaevASleCgTaskSEQ::PreProcessingImpl() {
const auto &a = GetInput().A;
size_t n = a.size();
flat_A_.resize(n * n);
for (size_t i = 0; i < n; ++i) {
for (size_t j = 0; j < n; ++j) {
flat_A_[(i * n) + j] = a[i][j];
}
}

return true;
}

bool SmyshlaevASleCgTaskSEQ::RunImpl() {
const auto &b = GetInput().b;
size_t n = b.size();

if (n == 0) {
return true;
}

std::vector<double> r = b;
std::vector<double> p = r;
std::vector<double> ap(n, 0.0);
std::vector<double> result(n, 0.0);

double rs_old = ComputeDotProduct(r, r);

const int max_iterations = static_cast<int>(n) * 2;
const double epsilon = 1e-9;

if (std::sqrt(rs_old) < epsilon) {
GetOutput() = result;
return true;
}

for (int iter = 0; iter < max_iterations; ++iter) {
ComputeAp(flat_A_, p, ap, n);

double p_ap = ComputeDotProduct(p, ap);

if (std::abs(p_ap) < 1e-15) {
break;
}

double alpha = rs_old / p_ap;
double rs_new = UpdateResultAndResidual(result, r, p, ap, alpha);

if (std::sqrt(rs_new) < epsilon) {
break;
}

double beta = rs_new / rs_old;
UpdateP(p, r, beta);

rs_old = rs_new;
}

GetOutput() = result;
return true;
}

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

} // namespace smyshlaev_a_sle_cg_seq
10 changes: 10 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/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"
}
87 changes: 87 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/tests/functional/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <gtest/gtest.h>

#include <array>
#include <cmath>
#include <cstddef>
#include <string>
#include <tuple>

#include "smyshlaev_a_sle_cg_seq/common/include/common.hpp"
#include "smyshlaev_a_sle_cg_seq/seq/include/ops_seq.hpp"
#include "util/include/func_test_util.hpp"
#include "util/include/util.hpp"

namespace smyshlaev_a_sle_cg_seq {

class SmyshlaevASleCgFuncTests : public ppc::util::BaseRunFuncTests<InType, OutType, TestType> {
public:
static std::string PrintTestParam(const TestType &test_param) {
return std::to_string(std::get<0>(test_param)) + "_" + std::get<1>(test_param);
}

protected:
void SetUp() override {
TestType params = std::get<static_cast<std::size_t>(ppc::util::GTestParamIndex::kTestParams)>(GetParam());
int test_id = std::get<0>(params);

if (test_id == 1) {
input_data_.A = {{4.0, 1.0}, {1.0, 3.0}};
input_data_.b = {9.0, 5.0};
expected_x_ = {2.0, 1.0};
} else if (test_id == 2) {
input_data_.A = {{10.0, -1.0, 2.0}, {-1.0, 11.0, -1.0}, {2.0, -1.0, 10.0}};
input_data_.b = {14.0, 18.0, 30.0};
expected_x_ = {1.0, 2.0, 3.0};
} else if (test_id == 3) {
input_data_.A = {{1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}};
input_data_.b = {5.0, -2.0, 8.0, 1.0};
expected_x_ = {5.0, -2.0, 8.0, 1.0};
} else if (test_id == 4) {
input_data_.A = {{4.0, 1.0}, {1.0, 3.0}};
input_data_.b = {1.0, 2.0};
expected_x_ = {1.0 / 11.0, 7.0 / 11.0};
}
}

bool CheckTestOutputData(OutType &output_data) final {
if (output_data.size() != expected_x_.size()) {
return false;
}
const double epsilon = 1e-6;
for (size_t i = 0; i < output_data.size(); ++i) {
if (std::fabs(output_data[i] - expected_x_[i]) > epsilon) {
return false;
}
}
return true;
}

InType GetTestInputData() final {
return input_data_;
}

private:
InType input_data_;
OutType expected_x_;
};

namespace {

TEST_P(SmyshlaevASleCgFuncTests, SleCgSeqTests) {
ExecuteTest(GetParam());
}

const std::array<TestType, 4> kTestParam = {std::make_tuple(1, "Simple2x2"), std::make_tuple(2, "Medium3x3"),
std::make_tuple(3, "IdentityMatrix4x4"), std::make_tuple(4, "Harder2x2")};

const auto kTestTasksList = std::tuple_cat(
ppc::util::AddFuncTask<SmyshlaevASleCgTaskSEQ, InType>(kTestParam, PPC_SETTINGS_smyshlaev_a_sle_cg_seq));

const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList);

const auto kPerfTestName = SmyshlaevASleCgFuncTests::PrintFuncTestName<SmyshlaevASleCgFuncTests>;

INSTANTIATE_TEST_SUITE_P(SleCgSeqFunctionalTests, SmyshlaevASleCgFuncTests, kGtestValues, kPerfTestName);

} // namespace
} // namespace smyshlaev_a_sle_cg_seq
90 changes: 90 additions & 0 deletions tasks/smyshlaev_a_sle_cg_seq/tests/performance/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <gtest/gtest.h>

#include <cmath>
#include <cstddef>
#include <random>
#include <utility>

#include "smyshlaev_a_sle_cg_seq/common/include/common.hpp"
#include "smyshlaev_a_sle_cg_seq/seq/include/ops_seq.hpp"
#include "util/include/perf_test_util.hpp"

namespace smyshlaev_a_sle_cg_seq {

class SmyshlaevASleCgPerfTests : public ppc::util::BaseRunPerfTests<InType, OutType> {
static constexpr int kSystemSize = 512;
InType input_data_{};
OutType expected_x_;

void SetUp() override {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(-1.0, 1.0);

CGMatrix a(kSystemSize, CGVector(kSystemSize, 0.0));
expected_x_.assign(kSystemSize, 1.0);
CGVector b(kSystemSize, 0.0);

for (int i = 0; i < kSystemSize; ++i) {
for (int j = i + 1; j < kSystemSize; ++j) {
double val = dis(gen);
a[i][j] = val;
a[j][i] = val;
}
}

for (int i = 0; i < kSystemSize; ++i) {
double row_sum = 0.0;
for (int j = 0; j < kSystemSize; ++j) {
if (i != j) {
row_sum += std::abs(a[i][j]);
}
}
a[i][i] = row_sum + 1.0;
}

for (int i = 0; i < kSystemSize; ++i) {
for (int j = 0; j < kSystemSize; ++j) {
b[i] += a[i][j] * expected_x_[j];
}
}

input_data_.A = std::move(a);
input_data_.b = std::move(b);
}

bool CheckTestOutputData(OutType &output_data) final {
if (output_data.size() != expected_x_.size()) {
return false;
}
const double epsilon = 1e-6;
for (size_t i = 0; i < output_data.size(); ++i) {
if (std::isnan(output_data[i]) || std::fabs(output_data[i] - expected_x_[i]) > epsilon) {
return false;
}
}
return true;
}

InType GetTestInputData() final {
return input_data_;
}
};

TEST_P(SmyshlaevASleCgPerfTests, RunPerfModes) {
ExecuteTest(GetParam());
}

namespace {

const auto kAllPerfTasks =
ppc::util::MakeAllPerfTasks<InType, SmyshlaevASleCgTaskSEQ>(PPC_SETTINGS_smyshlaev_a_sle_cg_seq);

const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks);

const auto kPerfTestName = SmyshlaevASleCgPerfTests::CustomPerfTestName;

INSTANTIATE_TEST_SUITE_P(RunModeTests, SmyshlaevASleCgPerfTests, kGtestValues, kPerfTestName);

} // namespace
} // namespace smyshlaev_a_sle_cg_seq
Loading