Merge pull request 'kadyrov_aydar_lab_7' (#178) from kadyrov_aydar_lab_7 into main

Reviewed-on: #178
This commit is contained in:
Alexey 2024-11-29 15:49:07 +04:00
commit 014088a385
4 changed files with 133 additions and 0 deletions

View File

@ -0,0 +1,41 @@
# Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений
## Задание
Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей.
### Описание работы программы
Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: *обычного и параллельного*.
  1. Обычный алгоритм
Функция minor(matrix, row, col) - Эта функция используется для удаления строки и столбца из матрицы, чтобы получить минор, который затем будет использован для вычисления детерминанта с помощью рекурсии.
Функция determinant(matrix) - Эта функция вычисляет детерминант матрицы с использованием метода Лапласа. Если матрица — это 2x2, то вычисление происходит напрямую. Для больших матриц она рекурсивно вызывает себя для подматриц.
  2. Параллельный алгоритм
parallel_determinant(matrix, num_threads=4) — Это функция, которая распределяет вычисления по нескольким потокам для ускорения работы.
worker(start_row, end_row) — Это вспомогательная функция, которая выполняет вычисления детерминанта на одном из диапазонов строк матрицы в параллельном потоке. Она используется в parallel_determinant для того, чтобы каждый поток мог вычислять часть детерминанта и потом результаты объединялись.
Библиотечные:
determinant(matrix) — Это основная функция для вычисления детерминанта матрицы с помощью рекурсивного метода Лапласа. Она использует минимальные матрицы (меньше 3x3) для расчёта детерминанта и рекурсивно вызывает себя для подматриц для матриц большего размера.
minor(matrix, row, col) — Вспомогательная функция, которая создаёт минор матрицы, удаляя указанную строку и столбец. Минор необходим для вычисления детерминанта по разложению Лапласа.
Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов.
### Результат работы программы:
Результаты работы программы в png картинках проекта.
#### Вывод
Параллельное выполнение нахождения детерминанта может привести к ускорению(но на больших данных, корректной настройки и оптимизации самого процесса), особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением.
# ВК
https://vk.com/video64471408_456239209?list=ln-EEX5GM4Xv1HnCnf9P1

View File

@ -0,0 +1,64 @@
import threading
import time
import random
import numpy as np
from concurrent.futures import ThreadPoolExecutor
def gaussian_determinant(matrix):
n = len(matrix)
mat = [row[:] for row in matrix]
for i in range(n):
max_row = max(range(i, n), key=lambda r: abs(mat[r][i]))
mat[i], mat[max_row] = mat[max_row], mat[i]
if mat[i][i] == 0:
return 0
for j in range(i + 1, n):
factor = mat[j][i] / mat[i][i]
for k in range(i, n):
mat[j][k] -= mat[i][k] * factor
det = 1
for i in range(n):
det *= mat[i][i]
return det
def parallel_determinant(matrix, num_threads=4):
n = len(matrix)
result = []
def worker(start_row, end_row):
partial_det = 1
for i in range(start_row, end_row):
partial_det *= matrix[i][i]
result.append(partial_det)
with ThreadPoolExecutor(max_workers=num_threads) as executor:
rows_per_thread = n // num_threads
futures = [executor.submit(worker, i * rows_per_thread, (i + 1) * rows_per_thread) for i in range(num_threads)]
for future in futures:
future.result()
return sum(result)
def generate_matrix(size):
return [[random.randint(1, 10) for _ in range(size)] for _ in range(size)]
matrix_sizes = [100, 300, 500]
num_threads = 4
for size in matrix_sizes:
print(f"\nБенчмарки для матрицы {size}x{size}:")
matrix = generate_matrix(size)
start = time.time()
det_seq = gaussian_determinant(matrix)
end = time.time()
print(f"Детерминант (последовательно, метод Гаусса): {det_seq}, время: {end - start:.5f} сек")
start = time.time()
det_par = parallel_determinant(matrix, num_threads=num_threads)
end = time.time()
print(f"Детерминант (параллельно): {det_par}, время: {end - start:.5f} сек")

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,28 @@
# Лабораторная работа 7. Балансировка нагрузки в распределённых системах при помощи открытых технологий на примерах
### Задание
Написать небольшое эссе (буквально несколько абзацев) своими словами (пожалуйста не пользуйтесь гуглом :).
  1. Какие алгоритмы и методы используются для балансировки нагрузки?
  2. Какие открытые технологии существуют для балансировки нагрузки?
  3. Как осуществляется балансировка нагрузки на базах данных?
  4. Реверс-прокси как один из элементов балансировки нагрузки.
***
ЭССЕ
---
**Балансировка нагрузки в распределённых системах**
Балансировка нагрузки — это процесс распределения запросов или задач между несколькими серверами или вычислительными ресурсами для оптимизации производительности и предотвращения перегрузок. Для реализации этой задачи применяются различные алгоритмы и методы, среди которых наиболее популярными являются: **круговой метод (round-robin)**, **наибольшая нагрузка** и **по наименьшей нагрузке**. Круговой метод равномерно распределяет запросы между серверами, в то время как методы по нагрузке основываются на вычислениях текущей загрузки серверов и направляют запросы на менее загруженные узлы.
Существует множество открытых технологий для балансировки нагрузки. Одной из самых популярных является **Nginx**, который может выполнять роль реверс-прокси и балансировщика нагрузки, распределяя входящий трафик между несколькими серверами. Также существует **HAProxy**, специализированный инструмент для балансировки нагрузки с высокими возможностями настройки и поддержкой различных алгоритмов. **Keepalived** используется для обеспечения отказоустойчивости системы путём управления виртуальными IP-адресами, что помогает поддерживать доступность сервисов даже в случае сбоя одного из серверов.
Балансировка нагрузки в базах данных отличается от обычной балансировки веб-запросов. Здесь она осуществляется на уровне запросов к базе данных, и чаще всего используется **репликация** и **шардинг**. Репликация позволяет создать несколько копий базы данных, и запросы могут направляться на менее загруженные реплики. Шардинг подразумевает разделение данных по нескольким серверам таким образом, что каждый сервер отвечает за часть данных, что позволяет распределить нагрузку и ускорить обработку запросов.
**Реверс-прокси** является важным элементом в балансировке нагрузки. Он принимает запросы от клиентов и перенаправляет их к подходящим серверам. Такой подход позволяет скрыть реальную архитектуру системы, повышает безопасность и упрощает управление трафиком. Реверс-прокси может работать в связке с балансировщиком нагрузки, чтобы обеспечить эффективное распределение запросов и улучшить общую производительность системы.
---