Merge pull request 'putilin_pavel_lab_5' (#253) from putilin_pavel_lab_5 into main
Reviewed-on: #253
This commit is contained in:
commit
35fa891625
37
putilin_pavel_lab_5/README.md
Normal file
37
putilin_pavel_lab_5/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Лабораторная работа №5: Вспоминаем математику или параллельное перемножение матриц
|
||||||
|
|
||||||
|
## Задание
|
||||||
|
|
||||||
|
Реализовать умножение двух квадратных матриц двумя способами: обычным и параллельным.
|
||||||
|
В параллельном алгоритме предусмотреть возможность задания количества потоков.
|
||||||
|
Каждый поток должен выполнять умножение матрицы в своей зоне ответственности.
|
||||||
|
|
||||||
|
### Требования:
|
||||||
|
1. Обычное умножение матриц.
|
||||||
|
2. Параллельное умножение с ручным заданием количества потоков.
|
||||||
|
3. Бенчмаркинг для матриц размером 100x100, 300x300 и 500x500.
|
||||||
|
|
||||||
|
## Структура проекта
|
||||||
|
|
||||||
|
Проект реализован в одном файле `main.py`. В нем содержатся:
|
||||||
|
- Обычное умножение матриц.
|
||||||
|
- Параллельное умножение с использованием многозадачности.
|
||||||
|
- Генерация случайных матриц для тестирования.
|
||||||
|
- Бенчмаркинг для проверки времени выполнения обоих алгоритмов.
|
||||||
|
- Тесты для проверки корректности умножения.
|
||||||
|
|
||||||
|
## Видео
|
||||||
|
|
||||||
|
https://cloud.mail.ru/public/Wzc4/FZCUnh5mk
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
В ходе лабораторной работы были реализованы два алгоритма умножения матриц:
|
||||||
|
обычный и параллельный. Параллельное умножение показало
|
||||||
|
значительное ускорение при больших матрицах.
|
||||||
|
Ожидаемо, для маленьких матриц разница
|
||||||
|
в производительности между алгоритмами была незначительной.
|
||||||
|
Параллельное умножение эффективно использует многозадачность
|
||||||
|
для уменьшения времени выполнения на крупных матрицах.
|
||||||
|
|
||||||
|
|
108
putilin_pavel_lab_5/main.py
Normal file
108
putilin_pavel_lab_5/main.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
def matrix_multiply(A, B):
|
||||||
|
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
if len(B) != cols_A:
|
||||||
|
raise ValueError("Количество столбцов первой матрицы должно совпадать с количеством строк второй матрицы.")
|
||||||
|
|
||||||
|
result = [[0] * cols_B for _ in range(rows_A)]
|
||||||
|
|
||||||
|
for i in range(rows_A):
|
||||||
|
for j in range(cols_B):
|
||||||
|
for k in range(cols_A):
|
||||||
|
result[i][j] += A[i][k] * B[k][j]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parallel_multiply_worker(A, B, result, row_index, cols_A, cols_B):
|
||||||
|
|
||||||
|
for j in range(cols_B):
|
||||||
|
result[row_index][j] = sum(A[row_index][k] * B[k][j] for k in range(cols_A))
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_matrix_multiply(A, B, num_threads):
|
||||||
|
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
if len(B) != cols_A:
|
||||||
|
raise ValueError("Количество столбцов первой матрицы должно совпадать с количеством строк второй матрицы.")
|
||||||
|
|
||||||
|
result = [[0] * cols_B for _ in range(rows_A)]
|
||||||
|
|
||||||
|
processes = []
|
||||||
|
for i in range(rows_A):
|
||||||
|
p = multiprocessing.Process(target=parallel_multiply_worker, args=(A, B, result, i, cols_A, cols_B))
|
||||||
|
processes.append(p)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
for p in processes:
|
||||||
|
p.join()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def generate_matrix(rows, cols):
|
||||||
|
return [[random.randint(1, 10) for _ in range(cols)] for _ in range(rows)]
|
||||||
|
|
||||||
|
def benchmark_matrix_multiplication():
|
||||||
|
sizes = [100, 300, 500]
|
||||||
|
num_threads = 4
|
||||||
|
|
||||||
|
for size in sizes:
|
||||||
|
print(f"Размер матрицы: {size}x{size}")
|
||||||
|
|
||||||
|
A = generate_matrix(size, size)
|
||||||
|
B = generate_matrix(size, size)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
matrix_multiply(A, B)
|
||||||
|
end_time = time.time()
|
||||||
|
print(f"Обычное умножение: {end_time - start_time:.4f} секунд")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
parallel_matrix_multiply(A, B, num_threads)
|
||||||
|
end_time = time.time()
|
||||||
|
print(f"Параллельное умножение: {end_time - start_time:.4f} секунд")
|
||||||
|
|
||||||
|
def test_matrix_multiply():
|
||||||
|
A = [
|
||||||
|
[1, 2],
|
||||||
|
[3, 4]
|
||||||
|
]
|
||||||
|
B = [
|
||||||
|
[5, 6],
|
||||||
|
[7, 8]
|
||||||
|
]
|
||||||
|
expected_result = [
|
||||||
|
[19, 22],
|
||||||
|
[43, 50]
|
||||||
|
]
|
||||||
|
result = matrix_multiply(A, B)
|
||||||
|
assert result == expected_result, f"Тест не пройден! Результат: {result}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
A = [
|
||||||
|
[1, 2]
|
||||||
|
]
|
||||||
|
B = [
|
||||||
|
[5, 6],
|
||||||
|
[7, 8]
|
||||||
|
]
|
||||||
|
matrix_multiply(A, B)
|
||||||
|
except ValueError:
|
||||||
|
print("Ошибка умножения матриц с несовпадающими размерами (ожидаемо).")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("Запуск тестов...")
|
||||||
|
test_matrix_multiply()
|
||||||
|
print("Тесты пройдены успешно!")
|
||||||
|
|
||||||
|
print("\nЗапуск бенчмаркинга...")
|
||||||
|
benchmark_matrix_multiplication()
|
Loading…
Reference in New Issue
Block a user