Merge pull request 'agliullov_daniyar_lab_6 is ready' (#183) from agliullov_daniyar_lab_6 into main
Reviewed-on: #183
This commit is contained in:
commit
75c2caf86d
Binary file not shown.
After Width: | Height: | Size: 227 KiB |
86
agliullov_daniyar_lab_6/main.py
Normal file
86
agliullov_daniyar_lab_6/main.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
np.seterr(over='ignore')
|
||||||
|
|
||||||
|
# Функция для вычисления детерминанта методом Гаусса
|
||||||
|
def compute_determinant_gauss(mat):
|
||||||
|
size = mat.shape[0]
|
||||||
|
matrix_copy = mat.astype(float) # Копируем матрицу, чтобы не изменять исходную
|
||||||
|
determinant = 1.0 # Начальное значение детерминанта
|
||||||
|
|
||||||
|
for k in range(size):
|
||||||
|
# Находим максимальный элемент в текущем столбце для уменьшения ошибок округления
|
||||||
|
max_index = np.argmax(np.abs(matrix_copy[k:size, k])) + k
|
||||||
|
if matrix_copy[max_index, k] == 0:
|
||||||
|
return 0 # Если на главной диагонали ноль, детерминант равен нулю
|
||||||
|
# Меняем местами строки
|
||||||
|
if max_index != k:
|
||||||
|
matrix_copy[[k, max_index]] = matrix_copy[[max_index, k]]
|
||||||
|
determinant *= -1 # Каждая перестановка меняет знак детерминанта
|
||||||
|
# Обнуляем элементы ниже главной диагонали
|
||||||
|
for m in range(k + 1, size):
|
||||||
|
multiplier = matrix_copy[m, k] / matrix_copy[k, k]
|
||||||
|
matrix_copy[m, k:] -= multiplier * matrix_copy[k, k:]
|
||||||
|
|
||||||
|
# Произведение элементов на главной диагонали
|
||||||
|
for j in range(size):
|
||||||
|
determinant *= matrix_copy[j, j]
|
||||||
|
return determinant
|
||||||
|
|
||||||
|
# Функция для параллельного вычисления детерминанта
|
||||||
|
def parallel_worker(index_range, mat):
|
||||||
|
size = mat.shape[0]
|
||||||
|
matrix_copy = mat.astype(float)
|
||||||
|
det = 1.0
|
||||||
|
|
||||||
|
for k in range(index_range[0], index_range[1]):
|
||||||
|
max_index = np.argmax(np.abs(matrix_copy[k:size, k])) + k
|
||||||
|
if matrix_copy[max_index, k] == 0:
|
||||||
|
return 0
|
||||||
|
if max_index != k:
|
||||||
|
matrix_copy[[k, max_index]] = matrix_copy[[max_index, k]]
|
||||||
|
det *= -1
|
||||||
|
for m in range(k + 1, size):
|
||||||
|
multiplier = matrix_copy[m, k] / matrix_copy[k, k]
|
||||||
|
matrix_copy[m, k:] -= multiplier * matrix_copy[k, k:]
|
||||||
|
return det
|
||||||
|
|
||||||
|
# Функция для параллельного вычисления детерминанта
|
||||||
|
def compute_parallel_determinant(mat, num_workers):
|
||||||
|
size = mat.shape[0]
|
||||||
|
block_size = size // num_workers
|
||||||
|
ranges = [(i * block_size, (i + 1) * block_size) for i in range(num_workers)]
|
||||||
|
|
||||||
|
with Pool(processes=num_workers) as pool:
|
||||||
|
results = pool.starmap(parallel_worker, [(block, mat) for block in ranges])
|
||||||
|
|
||||||
|
# Объединяем результаты
|
||||||
|
total_determinant = sum(results)
|
||||||
|
return total_determinant
|
||||||
|
|
||||||
|
# Функция для запуска тестов производительности
|
||||||
|
def execute_benchmarks():
|
||||||
|
sizes = [100, 300, 500] # Размеры матриц
|
||||||
|
for size in sizes:
|
||||||
|
random_matrix = np.random.rand(size, size) # Генерация случайной матрицы
|
||||||
|
print(f"--- Тест производительности для матрицы {size}x{size} ---")
|
||||||
|
|
||||||
|
# Последовательное вычисление детерминанта
|
||||||
|
start_time = time.time()
|
||||||
|
sequential_det = compute_determinant_gauss(random_matrix)
|
||||||
|
seq_duration = time.time() - start_time
|
||||||
|
print(f"Время последовательного вычисления для {size}x{size}: {seq_duration:.4f} секунд")
|
||||||
|
|
||||||
|
# Параллельное вычисление с различным количеством процессов
|
||||||
|
for workers in [1, 2, 4, 6, 8, 12, 16]:
|
||||||
|
start_time = time.time()
|
||||||
|
parallel_det = compute_parallel_determinant(random_matrix, workers)
|
||||||
|
par_duration = time.time() - start_time
|
||||||
|
speedup_ratio = seq_duration / par_duration if par_duration > 0 else 0
|
||||||
|
print(f"Параллельное время с {workers} процессами: {par_duration:.4f} секунд, Ускорение: {speedup_ratio:.2f}")
|
||||||
|
|
||||||
|
# Запуск тестов производительности
|
||||||
|
if __name__ == '__main__':
|
||||||
|
execute_benchmarks()
|
16
agliullov_daniyar_lab_6/readme.md
Normal file
16
agliullov_daniyar_lab_6/readme.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Аглиуллов Данияр ИСЭбд-41
|
||||||
|
# Лабораторная работа №6
|
||||||
|
|
||||||
|
Для повышения производительности при вычислении детерминанта для больших матриц была добавлена возможность параллельной обработки с использованием библиотеки multiprocessing. Это позволило значительно ускорить вычисления за счет распределения нагрузки между несколькими процессами.
|
||||||
|
|
||||||
|
Результаты тестов:
|
||||||
|
![изображение 1](../Screenshots/1.png)
|
||||||
|
|
||||||
|
Сравнение производительности:
|
||||||
|
|
||||||
|
• В тестах на матрицах размером 100x100, 300x300 и 500x500 было замечено, что параллельный алгоритм демонстрирует значительное сокращение времени выполнения по сравнению с обычным алгоритмом, особенно на больших матрицах. Это подтверждает эффективность использования многопоточности для задач, требующих больших вычислительных ресурсов.
|
||||||
|
|
||||||
|
• На малых размерах матриц (например, 100x100) преимущество было за последовательным умножением матрицы из-за накладных расходов на создание пула потоков. Однако при увеличении размера матрицы (300x300 и 500x500) преимущества параллельного подхода становились более очевидными.
|
||||||
|
• При превышении количества физических потоков процессора, производительность понижается за счет смены контекста при переключении виртуальных потоков на одном ядре
|
||||||
|
|
||||||
|
![Видео](https://disk.yandex.ru/d/MEZQvGM8u9OIBw)
|
Loading…
Reference in New Issue
Block a user