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

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

#include "task/include/task.hpp"

namespace kruglova_a_conjugate_gradient_sle {

struct SLEInput {
int size = 0;
std::vector<double> A;
std::vector<double> b;
};

using InType = SLEInput;
using OutType = std::vector<double>;
using TestType = std::tuple<int, std::string>;
using BaseTask = ppc::task::Task<InType, OutType>;

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

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

namespace kruglova_a_conjugate_gradient_sle {

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

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

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

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

#include "kruglova_a_conjugate_gradient_sle/common/include/common.hpp"

namespace kruglova_a_conjugate_gradient_sle {

namespace {
void MatrixVectorMultiply(const std::vector<double> &a, const std::vector<double> &p, std::vector<double> &ap, int n) {
for (int i = 0; i < n; ++i) {
ap[i] = 0.0;
for (int j = 0; j < n; ++j) {
ap[i] += a[(i * n) + j] * p[j];
}
}
}
} // namespace

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

bool KruglovaAConjGradSleSEQ::ValidationImpl() {
const auto &in = GetInput();
if (in.size <= 0) {
return false;
}

if (in.A.size() != static_cast<size_t>(in.size) * static_cast<size_t>(in.size)) {
return false;
}
if (in.b.size() != static_cast<size_t>(in.size)) {
return false;
}
return true;
}

bool KruglovaAConjGradSleSEQ::PreProcessingImpl() {
GetOutput().assign(GetInput().size, 0.0);
return true;
}

bool KruglovaAConjGradSleSEQ::RunImpl() {
const auto &a = GetInput().A;
const auto &b = GetInput().b;
int n = GetInput().size;
auto &x = GetOutput();

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

double rsold = 0.0;
for (int i = 0; i < n; ++i) {
rsold += r[i] * r[i];
}

const double tolerance = 1e-8;

for (int iter = 0; iter < n * 2; ++iter) {
MatrixVectorMultiply(a, p, ap, n);

double p_ap = 0.0;
for (int i = 0; i < n; ++i) {
p_ap += p[i] * ap[i];
}

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

double alpha = rsold / p_ap;
for (int i = 0; i < n; ++i) {
x[i] += alpha * p[i];
r[i] -= alpha * ap[i];
}

double rsnew = 0.0;
for (int i = 0; i < n; ++i) {
rsnew += r[i] * r[i];
}

if (std::sqrt(rsnew) < tolerance) {
break;
}

for (int i = 0; i < n; ++i) {
p[i] = r[i] + ((rsnew / rsold) * p[i]);
}
rsold = rsnew;
}
return true;
}

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

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

#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef> // Для std::size_t
#include <string>
#include <tuple>
#include <vector>

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

namespace kruglova_a_conjugate_gradient_sle {

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

protected:
void SetUp() override {
TestType params = std::get<2>(GetParam());
int size = std::get<0>(params);
std::string type = std::get<1>(params);

input_data_.size = size;
input_data_.A.assign(static_cast<std::size_t>(size) * static_cast<std::size_t>(size), 0.0);
input_data_.b.assign(size, 0.0);

if (type == "Identity") {
FillIdentity(size);
} else if (type == "Diagonal") {
FillDiagonal(size);
} else {
FillSpd(size);
}
}

bool CheckTestOutputData(OutType &output_data) final {
int n = input_data_.size;
double max_err = 0.0;
for (int i = 0; i < n; ++i) {
double ax = 0.0;
for (int j = 0; j < n; ++j) {
ax += input_data_.A[(static_cast<std::size_t>(i) * n) + j] * output_data[j];
}
max_err = std::max(max_err, std::abs(ax - input_data_.b[i]));
}
return max_err < 1e-4;
}

InType GetTestInputData() final {
return input_data_;
}

private:
InType input_data_;

void FillIdentity(int size) {
for (int i = 0; i < size; ++i) {
input_data_.A[(static_cast<std::size_t>(i) * size) + i] = 1.0;
input_data_.b[i] = static_cast<double>(i + 1);
}
}

void FillDiagonal(int size) {
for (int i = 0; i < size; ++i) {
input_data_.A[(static_cast<std::size_t>(i) * size) + i] = static_cast<double>(i + 1) * 10.0;
input_data_.b[i] = input_data_.A[(static_cast<std::size_t>(i) * size) + i];
}
}

void FillSpd(int size) {
for (int i = 0; i < size; ++i) {
double sum = 0.0;
for (int j = 0; j < size; ++j) {
if (i != j) {
auto val = static_cast<double>(((i + j) % 5) + 1);
input_data_.A[(static_cast<std::size_t>(i) * size) + j] = val;
input_data_.A[(static_cast<std::size_t>(j) * size) + i] = val;
sum += val;
}
}
input_data_.A[(static_cast<std::size_t>(i) * size) + i] = sum + 10.0;
input_data_.b[i] = static_cast<double>((i % 3) + 1);
}
}
};

TEST_P(KruglovaAFuncTestAConjGradSle, SolveSystem) {
ExecuteTest(GetParam());
}

namespace {
const std::array<TestType, 6> kTestParam = {std::make_tuple(1, "Size1"), std::make_tuple(3, "Identity"),
std::make_tuple(5, "Diagonal"), std::make_tuple(10, "Size10"),
std::make_tuple(50, "Size50"), std::make_tuple(101, "OddSize")};

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

const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList);
const auto kPerfTestName = KruglovaAFuncTestAConjGradSle::PrintFuncTestName<KruglovaAFuncTestAConjGradSle>;

INSTANTIATE_TEST_SUITE_P(SleSolverTests, KruglovaAFuncTestAConjGradSle, kGtestValues, kPerfTestName);
} // namespace

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

#include <cstddef>
#include <vector>

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

namespace kruglova_a_conjugate_gradient_sle {

class KruglovaAPerfTestAConjGradSle : public ppc::util::BaseRunPerfTests<InType, OutType> {
protected:
const int k_size = 2000;
InType input_data{};
void SetUp() override {
input_data.size = k_size;
input_data.A.resize(static_cast<size_t>(k_size) * static_cast<size_t>(k_size));
input_data.b.resize(k_size);

for (int i = 0; i < k_size; ++i) {
for (int j = 0; j < k_size; ++j) {
if (i == j) {
input_data.A[(i * k_size) + j] = static_cast<double>(k_size + 10);
} else {
input_data.A[(i * k_size) + j] = 1.0;
}
}
input_data.b[i] = static_cast<double>((i % 10) + 1);
}
}

bool CheckTestOutputData(OutType &output_data) final {
return output_data.size() == static_cast<size_t>(k_size);
}

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

TEST_P(KruglovaAPerfTestAConjGradSle, RunPerfPipeline) {
ExecuteTest(GetParam());
}

TEST_P(KruglovaAPerfTestAConjGradSle, RunPerfTask) {
ExecuteTest(GetParam());
}

namespace {

const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks<InType, KruglovaAConjGradSleSEQ

>(PPC_SETTINGS_kruglova_a_conjugate_gradient_sle);

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

const auto kPerfTestName = KruglovaAPerfTestAConjGradSle::CustomPerfTestName;

INSTANTIATE_TEST_SUITE_P(SequentialPerformance, KruglovaAPerfTestAConjGradSle, kGtestValues, kPerfTestName);

} // namespace

} // namespace kruglova_a_conjugate_gradient_sle
Loading