Merge pull request 'kosheev_maksim_lab_6' (#182) from kosheev_maksim_lab_6 into main
Reviewed-on: #182
This commit is contained in:
commit
1dc8fb7ecd
81
kosheev_maksim_lab_6/READMY.md
Normal file
81
kosheev_maksim_lab_6/READMY.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Лабораторная работа №5 - Параллельное вычисление детерминант матриц
|
||||||
|
|
||||||
|
## Задание
|
||||||
|
В данной лабораторной работе было необходимо реализовать вычисление детерминанта квадратной матрицы двумя способами:
|
||||||
|
1. Последовательное вычисление.
|
||||||
|
2. Параллельное вычисление с возможностью задания количества потоков.
|
||||||
|
|
||||||
|
Основная цель — изучить эффект параллельных вычислений и оценить прирост производительности при увеличении количества потоков.
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
Для запуска алгоритма вычисления детерминанта потребуется Python и модуль `multiprocessing`.
|
||||||
|
|
||||||
|
Запуск теста производительности:
|
||||||
|
```
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Результаты
|
||||||
|
|
||||||
|
Ниже представлены результаты бенчмарков для различных размеров матриц и разного количества потоков:
|
||||||
|
|
||||||
|
| Размер матрицы | Потоки | Время (последовательное) | Время (параллельное) | Ускорение |
|
||||||
|
|----------------|--------|--------------------------|-----------------------|-----------|
|
||||||
|
| **100x100** | 1 | 0.0100 s | 0.1957 s | 0.05 |
|
||||||
|
| | 2 | 0.0100 s | 0.1805 s | 0.06 |
|
||||||
|
| | 4 | 0.0100 s | 0.2080 s | 0.05 |
|
||||||
|
| | 6 | 0.0100 s | 0.3015 s | 0.03 |
|
||||||
|
| | 8 | 0.0100 s | 0.2370 s | 0.04 |
|
||||||
|
| | 12 | 0.0100 s | 0.2850 s | 0.04 |
|
||||||
|
| | 16 | 0.0100 s | 0.3188 s | 0.03 |
|
||||||
|
|
||||||
|
| Размер матрицы | Потоки | Время (последовательное) | Время (параллельное) | Ускорение |
|
||||||
|
|----------------|--------|--------------------------|-----------------------|-----------|
|
||||||
|
| **300x300** | 1 | 0.0970 s | 0.2766 s | 0.35 |
|
||||||
|
| | 2 | 0.0970 s | 0.2570 s | 0.38 |
|
||||||
|
| | 4 | 0.0970 s | 0.2360 s | 0.41 |
|
||||||
|
| | 6 | 0.0970 s | 0.2856 s | 0.34 |
|
||||||
|
| | 8 | 0.0970 s | 0.3120 s | 0.31 |
|
||||||
|
| | 12 | 0.0970 s | 0.3692 s | 0.26 |
|
||||||
|
| | 16 | 0.0970 s | 0.5351 s | 0.18 |
|
||||||
|
|
||||||
|
| Размер матрицы | Потоки | Время (последовательное) | Время (параллельное) | Ускорение |
|
||||||
|
|----------------|--------|--------------------------|-----------------------|-----------|
|
||||||
|
| **500x500** | 1 | 0.3000 s | 0.5301 s | 0.57 |
|
||||||
|
| | 2 | 0.3000 s | 0.3850 s | 0.78 |
|
||||||
|
| | 4 | 0.3000 s | 0.3512 s | 0.85 |
|
||||||
|
| | 6 | 0.3000 s | 0.3000 s | 1.00 |
|
||||||
|
| | 8 | 0.3000 s | 0.3300 s | 0.91 |
|
||||||
|
| | 12 | 0.3000 s | 0.3979 s | 0.75 |
|
||||||
|
| | 16 | 0.3000 s | 0.4740 s | 0.63 |
|
||||||
|
|
||||||
|
| Размер матрицы | Потоки | Время (последовательное) | Время (параллельное) | Ускорение |
|
||||||
|
|----------------|--------|--------------------------|-----------------------|-----------|
|
||||||
|
| **1000x1000** | 1 | 1.1871 s | 1.3527 s | 0.88 |
|
||||||
|
| | 2 | 1.1871 s | 1.1602 s | 1.02 |
|
||||||
|
| | 4 | 1.1871 s | 0.7971 s | 1.49 |
|
||||||
|
| | 6 | 1.1871 s | 0.6782 s | 1.75 |
|
||||||
|
| | 8 | 1.1871 s | 0.6263 s | 1.90 |
|
||||||
|
| | 12 | 1.1871 s | 0.6636 s | 1.79 |
|
||||||
|
| | 16 | 1.1871 s | 0.7715 s | 1.54 |
|
||||||
|
|
||||||
|
| Размер матрицы | Потоки | Время (последовательное) | Время (параллельное) | Ускорение |
|
||||||
|
|----------------|--------|--------------------------|-----------------------|-----------|
|
||||||
|
| **1200x1200** | 1 | 1.7012 s | 1.8796 s | 0.91 |
|
||||||
|
| | 2 | 1.7012 s | 1.5037 s | 1.13 |
|
||||||
|
| | 4 | 1.7012 s | 1.0827 s | 1.57 |
|
||||||
|
| | 6 | 1.7012 s | 0.8606 s | 1.98 |
|
||||||
|
| | 8 | 1.7012 s | 0.8093 s | 2.10 |
|
||||||
|
| | 12 | 1.7012 s | 0.8072 s | 2.11 |
|
||||||
|
| | 16 | 1.7012 s | 0.9291 s | 1.80 |
|
||||||
|
|
||||||
|
## Выводы
|
||||||
|
Из результатов видно, что ускорение при использовании параллельного алгоритма зависит от размера матрицы и количества потоков:
|
||||||
|
- Для небольших матриц (например, 100x100) параллельный алгоритм не даёт значительного ускорения из-за накладных расходов на создание потоков.
|
||||||
|
- Для больших матриц (например, 1000x1000 и 1200x1200) параллельный алгоритм даёт существенное ускорение, достигая оптимальных значений при использовании 8–12 потоков.
|
||||||
|
- Увеличение количества потоков сверх количества ядер процессора не улучшает производительность и даже может её снижать из-за накладных расходов на управление потоками.
|
||||||
|
|
||||||
|
Таким образом, для эффективного параллельного вычисления детерминанта матриц важно учитывать размер данных и правильно подбирать количество потоков.
|
||||||
|
|
||||||
|
## [Видео](https://disk.yandex.ru/i/Tov7E9dy7Kt5vA)
|
86
kosheev_maksim_lab_6/main.py
Normal file
86
kosheev_maksim_lab_6/main.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
# Функция для вычисления детерминанта с использованием метода Гаусса
|
||||||
|
def determinant_gauss(matrix):
|
||||||
|
n = matrix.shape[0]
|
||||||
|
A = matrix.astype(float) # Создаём копию матрицы, чтобы не изменять исходную
|
||||||
|
det = 1 # Начальная величина детерминанта
|
||||||
|
for i in range(n):
|
||||||
|
# Ищем максимальный элемент в текущем столбце для уменьшения ошибок округления
|
||||||
|
max_row = np.argmax(np.abs(A[i:n, i])) + i
|
||||||
|
if A[max_row, i] == 0:
|
||||||
|
return 0 # Если на диагонали ноль, то детерминант равен нулю
|
||||||
|
# Переставляем строки
|
||||||
|
if max_row != i:
|
||||||
|
A[[i, max_row]] = A[[max_row, i]]
|
||||||
|
det *= -1 # Каждая перестановка меняет знак детерминанта
|
||||||
|
# Обнуляем элементы ниже диагонали
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
factor = A[j, i] / A[i, i]
|
||||||
|
A[j, i:] -= factor * A[i, i:]
|
||||||
|
# Произведение элементов на диагонали
|
||||||
|
for i in range(n):
|
||||||
|
det *= A[i, i]
|
||||||
|
return det
|
||||||
|
|
||||||
|
|
||||||
|
# Функция для вычисления детерминанта с многопроцессностью
|
||||||
|
def parallel_determinant_worker(index_range, matrix):
|
||||||
|
n = matrix.shape[0]
|
||||||
|
A = matrix.astype(float)
|
||||||
|
det = 1
|
||||||
|
for i in range(index_range[0], index_range[1]):
|
||||||
|
# Ищем максимальный элемент в текущем столбце
|
||||||
|
max_row = np.argmax(np.abs(A[i:n, i])) + i
|
||||||
|
if A[max_row, i] == 0:
|
||||||
|
return 0
|
||||||
|
if max_row != i:
|
||||||
|
A[[i, max_row]] = A[[max_row, i]]
|
||||||
|
det *= -1
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
factor = A[j, i] / A[i, i]
|
||||||
|
A[j, i:] -= factor * A[i, i:]
|
||||||
|
return det
|
||||||
|
|
||||||
|
|
||||||
|
# Функция для параллельного вычисления детерминанта
|
||||||
|
def determinant_parallel(matrix, num_processes):
|
||||||
|
n = matrix.shape[0]
|
||||||
|
# Делим работу на блоки
|
||||||
|
block_size = n // num_processes
|
||||||
|
blocks = [(i * block_size, (i + 1) * block_size) for i in range(num_processes)]
|
||||||
|
|
||||||
|
with Pool(processes=num_processes) as pool:
|
||||||
|
results = pool.starmap(parallel_determinant_worker, [(block, matrix) for block in blocks])
|
||||||
|
|
||||||
|
# Объединяем результаты
|
||||||
|
det = sum(results)
|
||||||
|
return det
|
||||||
|
|
||||||
|
|
||||||
|
# Функция для запуска бенчмарков
|
||||||
|
def run_benchmarks():
|
||||||
|
matrix_sizes = [100, 300, 500,1000,1200] # Размеры матриц
|
||||||
|
for size in matrix_sizes:
|
||||||
|
matrix = np.random.rand(size, size) # Генерация случайной матрицы
|
||||||
|
print(f"--- Benchmark для матрицы {size}x{size} ---")
|
||||||
|
|
||||||
|
# Бенчмарк для последовательного вычисления детерминанта
|
||||||
|
start_time = time.time()
|
||||||
|
seq_det = determinant_gauss(matrix)
|
||||||
|
seq_time = time.time() - start_time
|
||||||
|
print(f"Последовательное время для {size}x{size}: {seq_time:.4f} секунд")
|
||||||
|
|
||||||
|
# Бенчмарк для параллельного вычисления с разным числом потоков
|
||||||
|
for num_processes in [1, 2, 4, 6, 8, 12, 16]:
|
||||||
|
start_time = time.time()
|
||||||
|
par_det = determinant_parallel(matrix, num_processes)
|
||||||
|
par_time = time.time() - start_time
|
||||||
|
speedup = seq_time / par_time if par_time > 0 else 0
|
||||||
|
print(f"Параллельное время с {num_processes} потоками: {par_time:.4f} секунд, Ускорение: {speedup:.2f}")
|
||||||
|
|
||||||
|
# Запуск бенчмарков
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run_benchmarks()
|
Loading…
Reference in New Issue
Block a user