Compare commits

...

5 Commits

Author SHA1 Message Date
Pavel
b9d8848113 putilin_pavel_lab_8 2024-12-05 19:18:51 +04:00
Pavel
a44c4d3885 putilin_pavel_lab_8 2024-12-05 19:14:33 +04:00
Pavel
9fc4526d6f putilin_pavel_lab_7 2024-12-05 18:56:56 +04:00
Pavel
c1e6b1abc5 putilin_pavel_lab_6 2024-12-05 18:55:20 +04:00
Pavel
f10d4d5c3a putilin_pavel_lab_6 2024-12-05 18:13:21 +04:00
4 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,31 @@
# Лабораторная работа №6: Нахождение детерминанта квадратной матрицы
## Задание
Необходимо реализовать два алгоритма нахождения детерминанта квадратной матрицы:
1. Обычное вычисление.
2. Параллельное вычисление с использованием многозадачности, где каждый поток будет вычислять часть матрицы.
### Требования:
1. Обычный алгоритм нахождения детерминанта (например, через рекурсию или разложение по строкам/столбцам).
2. Параллельный алгоритм с возможностью задания количества потоков.
3. Бенчмаркинг для матриц размером 100x100, 300x300 и 500x500.
## Структура проекта
Проект реализован в одном файле `main.py`, который включает в себя:
- Обычное вычисление детерминанта.
- Параллельное вычисление с использованием многозадачности.
- Генерацию случайных матриц для тестирования.
- Бенчмаркинг для измерения времени выполнения обоих алгоритмов.
- Тесты для проверки корректности вычисления детерминанта.
## Видео
https://cloud.mail.ru/public/31aJ/RrdgK3Rik
## Заключение
В ходе лабораторной работы были реализованы два алгоритма вычисления детерминанта матрицы: обычный и параллельный.
Параллельное вычисление показало значительное ускорение на больших матрицах,
что подчеркивает эффективность многозадачности в вычислительных задачах.

View File

@ -0,0 +1,75 @@
import numpy as np
import threading
import time
def determinant_gauss(matrix):
"""Вычисление детерминанта методом Гаусса"""
matrix_copy = matrix.astype(np.float64)
n = matrix_copy.shape[0]
det = 1.0
for i in range(n):
if matrix_copy[i, i] == 0:
for j in range(i + 1, n):
if matrix_copy[j, i] != 0:
matrix_copy[[i, j]] = matrix_copy[[j, i]]
det *= -1
break
det *= matrix_copy[i, i]
matrix_copy[i, i:] /= matrix_copy[i, i]
for j in range(i + 1, n):
factor = matrix_copy[j, i]
matrix_copy[j, i:] -= factor * matrix_copy[i, i:]
return det
def determinant_parallel(matrix, num_threads=2):
"""Параллельное вычисление детерминанта с использованием потоков"""
def compute_row(row, matrix_copy):
n = matrix_copy.shape[0]
for i in range(row, n, num_threads):
for j in range(i + 1, n):
if matrix_copy[i, i] == 0:
continue
factor = matrix_copy[j, i] / matrix_copy[i, i]
matrix_copy[j, i:] -= factor * matrix_copy[i, i:]
matrix_copy = matrix.astype(np.float64)
threads = []
for i in range(num_threads):
t = threading.Thread(target=compute_row, args=(i, matrix_copy))
threads.append(t)
t.start()
for t in threads:
t.join()
return matrix_copy[-1, -1]
def benchmark(sizes):
for size in sizes:
matrix = np.random.randint(1, 11, (size, size))
start_time = time.time()
det_regular = determinant_gauss(matrix)
end_time = time.time()
regular_time = end_time - start_time
start_time = time.time()
det_parallel = determinant_parallel(matrix, num_threads=4)
end_time = time.time()
parallel_time = end_time - start_time
print(f"Размер матрицы: {size}x{size}")
print(f"Детерминант (последовательно): {det_regular} | Время: {regular_time} секунд")
print(f"Детерминант (параллельно): {det_parallel} | Время: {parallel_time} секунд")
print("-" * 50)
benchmark([100, 300, 500])

View File

@ -0,0 +1,22 @@
## Эссе
Для балансировки нагрузки в распределённых системах используются различные алгоритмы и методы,
включая "круговую" (round-robin) и на основе минимальной нагрузки.
Первый метод направляет запросы по очереди на все серверы, второй —
направляет запросы на сервер с наименьшей текущей нагрузкой. Т акже используется алгоритм на основе хеширования,
при котором запросы направляются на сервер в зависимости от хеша параметров запроса,
что позволяет обеспечить распределение нагрузки более предсказуемо.
Открытые технологии для балансировки нагрузки включают Nginx, HAProxy и Apache HTTP Server.
Эти решения позволяют распределять нагрузку на несколько серверов, обеспечивая отказоустойчивость и масштабируемость приложений.
Эти технологии поддерживают различные методы балансировки, такие как круговая и на основе сессий.
Балансировка нагрузки на базах данных часто осуществляется с использованием репликации и шардирования.
Репликация позволяет распределить запросы на чтение между несколькими репликами базы данных, а шардирование делит базу данных на части (шарды),
каждая из которых обрабатывает часть запросов. Важно обеспечить консистентность данных при такой балансировке,
что достигается с помощью различных механизмов синхронизации и транзакций.
Реверс-прокси является важным элементом балансировки нагрузки.
Он принимает входящие запросы и перенаправляет их на соответствующие серверы.
Такой подход позволяет скрыть реальную инфраструктуру от пользователей, улучшить безопасность,
а также обеспечить централизованный контроль над нагрузкой, кэшированием и аутентификацией

View File

@ -0,0 +1,49 @@
### Устройство распределённых систем
Распределённая система — это набор программ или сервисов, которые работают вместе,
но находятся на разных компьютерах. Такие системы позволяют решать сложные задачи,
разбивая их на более простые части. Например, если взять социальную сеть,
то отдельные сервисы могут отвечать за сообщения, публикации или рекламу.
Это похоже на слаженную работу команды: каждый делает своё дело, но результат общий.
#### Почему выбирают распределённый подход?
Когда система становится слишком большой, поддерживать её как единое целое становится сложно.
Представьте огромный монолит: любое изменение может сломать что-то ещё.
В распределённых системах можно менять или улучшать отдельные сервисы,
не трогая остальные. Кроме того, если один сервис выйдет из строя, остальная система продолжит работать.
#### Для чего нужны оркестраторы?
Оркестраторы помогают распределять задачи между сервисами,
чтобы они работали согласованно. Например, они запускают новые экземпляры сервисов,
если нагрузка увеличилась, или перезапускают их в случае ошибки.
Без них управлять сотнями мелких сервисов вручную было бы очень трудно.
Конечно, сами оркестраторы добавляют немного головной боли, но они того стоят.
#### Зачем очереди сообщений?
Очереди нужны, чтобы сервисы могли обмениваться задачами,
как сотрудники офиса передают друг другу записки.
Например, один сервис обрабатывает заказы, а другой — отправляет уведомления.
Если заказы приходят быстрее, чем их успевают обрабатывать,
очередь помогает не терять данные и обрабатывать всё по мере готовности.
#### Преимущества и недостатки распределённых систем
Главный плюс — гибкость. Можно улучшать отдельные части,
не затрагивая всю систему. А ещё такие системы проще масштабировать:
если чего-то не хватает, просто добавляешь мощности туда, где это нужно.
Но есть и минусы. Например, сложность:
сервисы должны "разговаривать" друг с другом через сеть, а это дополнительные ошибки и задержки.
#### Нужны ли параллельные вычисления?
Параллельные вычисления полезны, когда нужно делать много одинаковых задач.
Например, обработка большого объёма данных или сложные расчёты.
Но если одна задача зависит от другой, параллельность может только всё усложнить.
Тут уже важен баланс — где стоит делить задачи, а где нет.
Распределённые системы — это как пазл. Каждый кусочек важен,
но собрать их вместе так, чтобы всё работало идеально, — это искусство.
Однако, несмотря на сложности, такой подход открывает огромные возможности