diff --git a/tasks/konovalov_s_seidel_iterative_method/common/include/common.hpp b/tasks/konovalov_s_seidel_iterative_method/common/include/common.hpp new file mode 100644 index 0000000000..67c2074a10 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace konovalov_s_seidel_iterative_method { + +using InType = int; +using OutType = std::vector; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/data/pic.jpg b/tasks/konovalov_s_seidel_iterative_method/data/pic.jpg new file mode 100644 index 0000000000..637624238c Binary files /dev/null and b/tasks/konovalov_s_seidel_iterative_method/data/pic.jpg differ diff --git a/tasks/konovalov_s_seidel_iterative_method/data/sys_1.txt b/tasks/konovalov_s_seidel_iterative_method/data/sys_1.txt new file mode 100644 index 0000000000..ef2c91e5a3 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/data/sys_1.txt @@ -0,0 +1 @@ +3 5 10 1 1 2 10 1 2 2 10 12 13 14 1 1 1 \ No newline at end of file diff --git a/tasks/konovalov_s_seidel_iterative_method/data/sys_2.txt b/tasks/konovalov_s_seidel_iterative_method/data/sys_2.txt new file mode 100644 index 0000000000..98202614a1 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/data/sys_2.txt @@ -0,0 +1 @@ +3 100 4 -1 1 1 6 2 -1 -2 5 4 9 2 1 1 1 \ No newline at end of file diff --git a/tasks/konovalov_s_seidel_iterative_method/data/sys_3.txt b/tasks/konovalov_s_seidel_iterative_method/data/sys_3.txt new file mode 100644 index 0000000000..f1b1f72a70 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/data/sys_3.txt @@ -0,0 +1 @@ +4 10 20.9 1.2 2.1 0.9 1.2 21.2 1.5 2.5 2.1 1.5 19.8 1.3 0.9 2.5 1.3 32.1 21.7 27.46 28.76 49.72 0.8 1 1.2 1.4 \ No newline at end of file diff --git a/tasks/konovalov_s_seidel_iterative_method/info.json b/tasks/konovalov_s_seidel_iterative_method/info.json new file mode 100644 index 0000000000..b57d83e25d --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Sergey", + "last_name": "Konovalov", + "middle_name": "Alexandrovich", + "group_number": "3823Б1Пр3", + "task_number": "2" + } +} diff --git a/tasks/konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp b/tasks/konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp new file mode 100644 index 0000000000..090e415fe1 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace konovalov_s_seidel_iterative_method { + +class KonovalovSSeidelMethodMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit KonovalovSSeidelMethodMPI(const InType &in); + + private: + + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + static std::vector IterationStep(int mtr_szie, int diff, int rank, std::vector &_A, std::vector &_B, std::vector &X_gl); + void InitMatrixA(int size, int fmax, std::vector &A, int diff); + void InitMatrixB(int size, int fmax, std::vector &B); + void DataDistr(int size, int diff, int mtr_size); + void DataRecv(std::vector &A_local, std::vector &B_local, int matrix_size, int diff); +}; + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/mpi/src/ops_mpi.cpp b/tasks/konovalov_s_seidel_iterative_method/mpi/src/ops_mpi.cpp new file mode 100644 index 0000000000..e99fe3116d --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/mpi/src/ops_mpi.cpp @@ -0,0 +1,184 @@ +#include "konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp" + +#include + +#include +#include + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace konovalov_s_seidel_iterative_method { + +KonovalovSSeidelMethodMPI::KonovalovSSeidelMethodMPI(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = std::vector(GetInput(), 0.0); +} + +bool KonovalovSSeidelMethodMPI::ValidationImpl() { + return GetInput() > 3; +} + +bool KonovalovSSeidelMethodMPI::PreProcessingImpl() { + return true; +} + +void KonovalovSSeidelMethodMPI::InitMatrixA(int size, int fmax, std::vector &A, int _diff) { + int diff = _diff; + int x = size + rand() % fmax; + + for (int i = 0; i < size; i++) { + int sum = 0; + int j = 1; + do { + int diff_addr_pos = i * size + i + j; + int diff_addr_neg = i * size + i - j; + + if (diff_addr_neg > 0 && diff_addr_neg >= i * size) { + A[diff_addr_neg] = x * (diff - j); + sum += A[diff_addr_neg]; + } + + if (diff_addr_pos < size * size && i + j < size) { + A[diff_addr_pos] = x * (diff - j); + sum += A[diff_addr_pos]; + } + j++; + } while (j < diff); + A[i * size + i] = abs(sum + 1); + } +} + +void KonovalovSSeidelMethodMPI::InitMatrixB(int size, int fmax, std::vector &B) { + for (int i = 0; i < size; i++) { + B[i] = pow(size + rand() % fmax, 2); + } +} + + +std::vector KonovalovSSeidelMethodMPI::IterationStep(int mtr_size, int diff, int rank, std::vector &_A, + std::vector &_B, std::vector &X_gl) { + std::vector X = X_gl; + std::vector X_ret(diff, 0.0); + std::vector X_new(mtr_size, 0.0); + + for (int i = 0; i < diff; i++) { + int diag = (rank - 1) * (diff) + i; + X_new[diag] = (double)_B[i] / (double)_A[diag + i * mtr_size]; + for (int j = 0; j < mtr_size; j++) { + if (i * mtr_size + j == diag) { + continue; + } + + X_new[diag] -= ((double)_A[i * mtr_size + j] / (double)_A[diag + i * mtr_size]) * X[j]; + } + + X[diag] = round(X_new[diag] * 1000) / 1000; + X_ret[i] = X[diag]; + } + return X_ret; +} + +void KonovalovSSeidelMethodMPI::DataDistr(int matrix_size, int size, int diff) { + std::vector A; + std::vector B; + + A.resize(matrix_size * matrix_size, 0); + B.resize(matrix_size, 0); + + InitMatrixA(matrix_size, 10, A, matrix_size / (size - 1)); + InitMatrixB(matrix_size, 10, B); + + int r = matrix_size * diff; + for (int i = 1; i < size; i++) { + int p = (i - 1) * r; + MPI_Send(&A[p], r, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&B[(i - 1) * diff], diff, MPI_INT, i, 0, MPI_COMM_WORLD); + } +} + +void KonovalovSSeidelMethodMPI::DataRecv(std::vector &A_local, std::vector &B_local, int matrix_size, + int diff) { + MPI_Status s; + A_local.resize(matrix_size * diff); + B_local.resize(diff); + + MPI_Recv(&A_local[0], matrix_size * diff, MPI_INT, 0, 0, MPI_COMM_WORLD, &s); + MPI_Recv(&B_local[0], diff, MPI_INT, 0, 0, MPI_COMM_WORLD, &s); +} + +bool KonovalovSSeidelMethodMPI::RunImpl() { + srand(time(NULL)); + + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + int matrix_size = GetInput(); + int diff = matrix_size / (size - 1); + + std::vector gl_x_vec(size * diff, 0.0); + std::vector local_x_vec(diff, 0.0); + std::vector colors(matrix_size); + std::vector A_local; + std::vector B_local; + double epsi = 0.001; + int iter = 10; + bool stop_calc = true; + + gl_x_vec.resize(matrix_size, 0.0); + colors.resize(matrix_size, 0); + + if (rank == 0) { + DataDistr(matrix_size, size, diff); + } else { + DataRecv(A_local, B_local, matrix_size, diff); + } + + while (iter != 0) { + bool cover_tracker = true; + if (rank != 0) { + local_x_vec = IterationStep(matrix_size, diff, rank, A_local, B_local, gl_x_vec); + + for (int i = 0; i < diff; i++) { + cover_tracker = cover_tracker && (std::fabs(local_x_vec[i] - gl_x_vec[(rank)*diff + i]) < epsi); + } + } + + MPI_Barrier(MPI_COMM_WORLD); + + if (rank == 0) { + std::vector counts(size, diff); + std::vector displacements(size); + + for (int i = 0; i < size; i++) { + displacements[i] = diff * i; + } + + MPI_Gatherv(&local_x_vec[0], diff, MPI_DOUBLE, &gl_x_vec[0], counts.data(), displacements.data(), MPI_DOUBLE, 0, + MPI_COMM_WORLD); + } else { + MPI_Gatherv(&local_x_vec[0], diff, MPI_DOUBLE, NULL, NULL, NULL, MPI_DOUBLE, 0, MPI_COMM_WORLD); + } + MPI_Bcast(&gl_x_vec[0], size * diff, MPI_DOUBLE, 0, MPI_COMM_WORLD); + + MPI_Allreduce(&cover_tracker, &stop_calc, 1, MPI_C_BOOL, MPI_LAND, MPI_COMM_WORLD); + + if (stop_calc) { + break; + } + iter--; + } + for (int i = diff; i < size * diff; i++) { + GetOutput()[i - diff] = gl_x_vec[i]; + } + return true; + } + + bool KonovalovSSeidelMethodMPI::PostProcessingImpl() { + return true; + } + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/report.md b/tasks/konovalov_s_seidel_iterative_method/report.md new file mode 100644 index 0000000000..8559d1788f --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/report.md @@ -0,0 +1,134 @@ +# <Подсчет буквенных символов в строке> + +- Student: <Коновалов Сергей Александрович>, group <3823Б1Пр3> +- Technology: +- Variant: <19> + +## 1. Introduction +Задача решения итеративным методом Зейделя систем линейных алгебраических уравнений вида Ax=b, где +- A - матрица коэффициентов при неизвестных +- b - вектор свободных членов +- x - вектор неизвестных + +Суть метода можно описать так: из каждого уравнения выражается неизвестное, соответствующее коэффициенту на диагонали матрицы A, выбираются начальные приближения неизвестных для нулевого цикла (как правило, каждая неизвестная = 0) и выполняется нулевой цикл. +На нулевом цикле используются начальные приближения для вычисления новых значений неизвестных, при этом новые значения, полученные на предыдущих итерациях каждого цикла, используются в последующих вычисления оставшихся неизвестных. +Новые значения неизвестных, полученные в результате работы алгоритма, сохраняются и используются как начальные приближения в следующем цикле. +Алгоритм заканчивает работу в двух случаях: +- Положительный - необходимой точности вычислений удалось достичь за количество итераций меньше максимального +- Негативный - достигнуто максимальное количество итераций, т.е. требуемая точность не достигнута + +Известно, что метод зейделя обладает наилучшей сходимостью (она обеспечивается диагонально-доминантными матрицами коэффициентов, так что отношение любых других коэффициентов к диагональному в одной строке меньше единицы), вплоть до точного результата. + +Метод зейделя широко используется для описания взаимодействия плотных объектов в 3D моделировании. + +## 2. Problem Statement +Одной из главных проблем стало представление тестовых данных. +Изначально предполагалось использование внешних источников, в которых некоторым образом были бы записаны матрицы A и b, размер матрицы и максимальное количество итераций, а так же верный ответ. Тем самым алгоритм можно было бы испытывать на реальных системах. +Однако, начав реализовывать параллельную версию, от этой идеи пришлось отказаться и перейти к генерации данных. + +К генерации данных, в свою очередь, вынудило перейти изучение вопроса о параллелизации метода Гаусса-Зейделя. +Из изученного материала я выяснил, что принцип его параллелизации лежит в нахождении независимых неизвестных - тех, что не учавствуют в уравнениях друг друга, т.е. чьи симметричные коэффициенты равны 0 (пр.: х1,3 = х3,1 = 0). +Подобных переменных в системе может быть как несколько (пр.: 2 блока попарно независимых неизвесных при размере вектора 4), так и не быть вовсе. За определение подобных неизвестных отвечает алгоритм закраски графа (забегая вперед, матрица коэффициентов представлена в виде одномерного вектора): + +``` +std::vector A = _A; // coefficient matrix.int + std::vector color(size); // colors of rows. + for (int i = 0; i < size; ++i) { + color[i] = -1; + } + for (int i = 0; i < size; ++i) { + int m = 0; + for (int j = 0; j < i; j++) { + if (A[i * size + j] != 0 && color[j] == m) { + ++m; + } + } + color[i] = m; + } +``` + +Его работу можно описать так: проходя по матрице коэффициентов, алгоритм считает ненулевые элементы в рядах матрицы, возвращая полученные значения для каждого ряда. Индексы с одинаковыми значениями принадлежат одному блоку независимых неизвестных, следовательно могут быть посчитаны в любом порядке, и как итог, их вычисление можно вынести на разные процессы для одновременного подсчета. Единственное, остается зависимость в подсчете блоков (первым должен быть посчитан блок содержащий уравнение х0, затем блок содержащий х1 и т.д.), однако достаточно легко решается нумерацией блоков. + +Сам алгоритм закраски графа в итоговой версии не используется, но он привел к итоговому решению. + + +## 3. Baseline Algorithm (Sequential) +Последовательный алгоритм: +- Считывает входные данные +- Генерирует матрицы методами InitMatrixA() и InitMatrixB() соотретственно, основываясь на количестве неизвестных (в GetInput()) +- Выполняет функцию Iterativeprocess() +- Полученный результат передает GetOutput() + +Алгоритм содержится в Iterativeprocess() в своей самой рапространенной реализации. + +Алгоритм генерации данных в большей степени заточен на MPI реализацию, поэтому параллельная версия генерирует несколько другие матрицы, что не критично для тестов функционала. + +srand(time(NULL)) используется для обновления счетчика рандомайзера для получения случайных результатов каждый раз при запуске генераций. + +## 4. Parallelization Scheme +Идея распараллеливания вычислений заключается в следующем: +Разделение обязанностей: +### 1. Процесс-дистрибьютор +- Один из процессов (ранг 0) выступает в роли дистрибьютора данных. +- Он считывает водные данные, генерирует матрицы на их основе, а также в зависимости от запущенных процессов таким образом, что каждый процесс будет высчитывать одинаковое количество блоков независимых неизвестных, поровну разделяя нагрузку. +- - Этот процесс единственный, кто имеет полную матрицы коэффициентов и свободных членов (только в функции DataDistr()). +- Процесс делит полученные матрицы между процессами-получателями и отправляет их. +- - Передача осуществляется логикой Send-Recv в том числе для синхронизации действий потоков. +- После того, как строки были отправлены, процесс попадает в общий цикл и встает в состояние ожидания пока другие процессы не закончат шаг итерации Зейделя. +- Затем процесс собирает новые значения локальных векторов неизвестных, объединяет их в глобальный вектор новых значений неизвестных gl_x_vec, передавая это новое значение остальным процессам через Bcast. +### 2. Процесс-получатель +- Каждый процесс находится в состоянии ожидания входящих сообщений и инициализирует массив локальной матрицы коэффициентов размером по размеру из GetInput(), а также по известному ему количеству процессов, равному количеству блоков независимых неизвестных, и следовательно, количеству высчитываемых процессом уравнений, аналогично с матрицей свободных членов. +- - Передача осуществляется логикой Send-Recv в том числе для синхронизации действий потоков. +- С полученными данными процесс начинает вычисление шагов метода Зейделя. +- - Функция, реализующая алгоритм была модифицирована под взаимодействие с процессом, добавлены переменные с адресами диагональных коэффициентов, изменен способ обращения к массиву и главное - была убрана цикличность до достижения точности. +- Вычислив новые значения своих неизвестных, процесс сравнивает новые значения со старыми, хранящимися в gl_x_vec. +- - Используется логическое И на предмет наличия неизвестного, всё ещё не достигшего необходимой точности на каждом процессе, результат сохраняется в переменной cover_tracker. +- В конце общего цикла процессы обмениваются локальными данными о неизвестных, получая взамен новые данные gl_x_vec +### 3. Общая часть +- Закончив обмен начальными данными все процессы попадают в общий цикл, имитирующий итерации метода Зейделя. +- - Каждый процесс имеет свой итератор цикла, а так же флаг выхода из общего цикла. +- - В конце каждой итерации итератор уменьшается на 1 и делается проверка флага: +- - - Используется функция Allreduce по переменной cover_tracker с использованием аргумента MPI_LAND: пока есть хоть один процесс, возвращающий при запросе false, то точность не достигнута, цикл продолжается (Нулевой процесс всегда возвращает true, поэтому он не влияет на результат умножения). +- При завершении общего цикла, процессы передают данные gl_x_vec в GetOutput() + +## 5. Implementation Details +Тестовые данные хранятся в папке /data с ключевым словом "text_line_[correct_ans]". Файл открывается и обрабатывается в классе теста. +Ввиду своей простоты, весь алгоритм реализован в методе RunImpl(). + +## 6. Experimental Setup +Проект запускался в WSL с помощью докера. +- CPU: Intel Xeon CPU E5-2678 v3 2.50GHz +- Cores: 12 +- RAM: 7.5 Gb +- OS: Ubuntu 24.04.3 LTS +- Compiler: GCC +- Build type: Release +- Environment: PPC_NUM_PROC +- Data: tasks/konovalov_s_symbol_count/data + +## 7. Results and Discussion + +### 7.1 Correctness +Функциональный тест сверяет выходные данные на предмет адекватности - вероятность того, что случайно сгенерированная система имеет решение в виде вектора нулей маловероятно. Для параллельной версии, проверяются результаты каждого процесса. +Алгоритм справился с фунциональными тестами, как на последовательной, так и на параллельной версии. + +### 7.2 Performance +Present time, speedup and efficiency. Example table: + +| Mode | Count | Time, s | Speedup | Efficiency | +|-------------|-------|---------|---------|------------| +| seq | 1 | 1.234 | 1.00 | N/A | +| mpi | 2 | 0.700 | 1.76 | 88.0% | +| omp | 4 | 0.390 | 3.16 | 79.0% | + + + +## 9. References +1. <(https://www.opennet.ru/)> +2. +3. + +## Appendix (Optional) +```cpp +// Short, readable code excerpts if needed +``` \ No newline at end of file diff --git a/tasks/konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp b/tasks/konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp new file mode 100644 index 0000000000..18290a00ea --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace konovalov_s_seidel_iterative_method { + +class KonovalovSSeidelMethodSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit KonovalovSSeidelMethodSEQ(const InType &in); + + private: + int size = 0; + int max_iter = 0; + int iter = 0; + + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + static std::vector IterationProcess(std::vector &_A, std::vector &_B, int _iter, + double _epsi); + void InitMatrixA(int size, int fmax, std::vector &A, int diff); + void InitMatrixB(int size, int fmax, std::vector &B); +}; + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/seq/src/ops_seq.cpp b/tasks/konovalov_s_seidel_iterative_method/seq/src/ops_seq.cpp new file mode 100644 index 0000000000..a8be87b969 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/seq/src/ops_seq.cpp @@ -0,0 +1,110 @@ +#include "konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp" + +#include +#include + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace konovalov_s_seidel_iterative_method { + +KonovalovSSeidelMethodSEQ::KonovalovSSeidelMethodSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = std::vector(size, 0.0); +} + +bool KonovalovSSeidelMethodSEQ::ValidationImpl() { + if(GetInput() < 16) return false; + return true; +} + +bool KonovalovSSeidelMethodSEQ::PreProcessingImpl() { + size = GetInput(); + + return true; +} + +void KonovalovSSeidelMethodSEQ::InitMatrixA(int size, int fmax, std::vector &A, int _diff) { + int diff = _diff; + int x = rand() % fmax; + + for (int i = 0; i < size; i++) { + int sum = 0; + int j = 1; + do { + int diff_addr_pos = i * size + i + j; + int diff_addr_neg = i * size + i - j; + + if (diff_addr_neg > 0 && diff_addr_neg >= i * size) { + A[diff_addr_neg] = x * (diff - j); + sum += A[diff_addr_neg]; + } + + if (diff_addr_pos < size*size && i + j < size) { + A[diff_addr_pos] = x * (diff - j); + sum += A[diff_addr_pos]; + } + j++; + } while (j < diff); + A[i * size + i] = abs(sum + 1); + } +} + +void KonovalovSSeidelMethodSEQ::InitMatrixB(int size, int fmax, std::vector &B) { + for (int i = 0; i < size; i++) { + B[i] = rand() % fmax; + } + +} + +std::vector KonovalovSSeidelMethodSEQ::IterationProcess(std::vector &_A, std::vector &_B, int _iter, + double _epsi) { + double epsi = _epsi; + int iter = _iter; + std::vector X(_B.size(), 0.0); + + std::vector X_new(_B.size(), 0.0); + + while (iter != 0) { + bool flag = true; + for (long unsigned int i = 0; i < _B.size(); i++) { + X_new[i] = _B[i] / _A[i * _B.size() + i]; + for (long unsigned int j = 0; j < _B.size(); j++) { + if (j == i) { + continue; + } + X_new[i] -= (_A[i * _B.size() + j] / _A[i * _B.size() + i]) * X[j]; + } + + flag = flag && (std::fabs(X_new[i] - X[i]) < epsi); + + X[i] = round(X_new[i] * 1000) / 1000; + } + iter--; + + if (flag) { + break; + } + } + return X; +} + +bool KonovalovSSeidelMethodSEQ::RunImpl() { + srand(time(NULL)); + + std::vector A(size*size, 0.0); + std::vector B(size, 0.0); + InitMatrixA(size, 10, A, size/4); + InitMatrixB(size, 10, B); + GetOutput() = IterationProcess(A, B, 10, 0.001); + + return true; + +} + +bool KonovalovSSeidelMethodSEQ::PostProcessingImpl() { + return true; +} + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/settings.json b/tasks/konovalov_s_seidel_iterative_method/settings.json new file mode 100644 index 0000000000..b1a0d52574 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/settings.json @@ -0,0 +1,7 @@ +{ + "tasks_type": "processes", + "tasks": { + "mpi": "enabled", + "seq": "enabled" + } +} diff --git a/tasks/konovalov_s_seidel_iterative_method/tests/.clang-tidy b/tasks/konovalov_s_seidel_iterative_method/tests/.clang-tidy new file mode 100644 index 0000000000..ef43b7aa8a --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/tests/.clang-tidy @@ -0,0 +1,13 @@ +InheritParentConfig: true + +Checks: > + -modernize-loop-convert, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-avoid-non-const-global-variables, + -misc-use-anonymous-namespace, + -modernize-use-std-print, + -modernize-type-traits + +CheckOptions: + - key: readability-function-cognitive-complexity.Threshold + value: 50 # Relaxed for tests diff --git a/tasks/konovalov_s_seidel_iterative_method/tests/functional/main.cpp b/tasks/konovalov_s_seidel_iterative_method/tests/functional/main.cpp new file mode 100644 index 0000000000..b40808f567 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/tests/functional/main.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp" +#include "konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace konovalov_s_seidel_iterative_method { + +class KonovalovSRunFuncTestsProcesses2 : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + std::string test_name = std::get<0>(test_param); + return test_name; + } + + protected: + void SetUp() override { + TestType params = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + + int _size = std::get<1>(params); + input_data_ = _size; + incorrect_output.resize(_size, 0.0); + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data != incorrect_output; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType incorrect_output; +}; + +namespace { + +TEST_P(KonovalovSRunFuncTestsProcesses2, SeidelMethodF) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = {std::make_tuple("sys_1", 32), std::make_tuple("sys_2", 64), + std::make_tuple("sys_3", 128)}; + +const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_konovalov_s_seidel_iterative_method), + ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_konovalov_s_seidel_iterative_method)); + +// const auto kTestTasksList = +// std::tuple_cat( +// ppc::util::AddFuncTask(kTestParam, +// PPC_SETTINGS_konovalov_s_seidel_iterative_method)); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = KonovalovSRunFuncTestsProcesses2::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(LinearSysOfEqFromFileF, KonovalovSRunFuncTestsProcesses2, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace konovalov_s_seidel_iterative_method diff --git a/tasks/konovalov_s_seidel_iterative_method/tests/performance/main.cpp b/tasks/konovalov_s_seidel_iterative_method/tests/performance/main.cpp new file mode 100644 index 0000000000..063d0c4835 --- /dev/null +++ b/tasks/konovalov_s_seidel_iterative_method/tests/performance/main.cpp @@ -0,0 +1,42 @@ +#include + +#include "konovalov_s_seidel_iterative_method/common/include/common.hpp" +#include "konovalov_s_seidel_iterative_method/mpi/include/ops_mpi.hpp" +#include "konovalov_s_seidel_iterative_method/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace konovalov_s_seidel_iterative_method { + +class KonovalovSRunPerfTestsProcesses2 : public ppc::util::BaseRunPerfTests { + void SetUp() override { + input_data_ = 2048; + incorrect_output.resize(input_data_, 0.0); + } + + bool CheckTestOutputData(OutType &output_data) final { + return output_data != incorrect_output; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType incorrect_output; +}; + +TEST_P( KonovalovSRunPerfTestsProcesses2, SeidelPTests) { + ExecuteTest(GetParam()); +} + +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_konovalov_s_seidel_iterative_method); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = KonovalovSRunPerfTestsProcesses2::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(SeidelPTestRun, KonovalovSRunPerfTestsProcesses2, kGtestValues, kPerfTestName); + +} // namespace konovalov_s_seidel_iterative_method