artamonova_tatyana_lab_5 is ready #204
36
artamonova_tatyana_lab_5/README.md
Normal file
36
artamonova_tatyana_lab_5/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
# Лабораторная работа №5 ПИбд-42 Артамоновой Татьяны
|
||||||
|
|
||||||
|
## Запуск лабораторной работы
|
||||||
|
|
||||||
|
1. Установить библиотеки Python и NumPy
|
||||||
|
3. Запустить скрипт matrix.py с помощью команды: *python matrix.py*
|
||||||
|
|
||||||
|
## Используемые технологии
|
||||||
|
|
||||||
|
- Язык программирования: Python
|
||||||
|
- Библиотеки:
|
||||||
|
* numpy: Для работы с массивами и матрицами
|
||||||
|
* multiprocessing: Для параллельного выполнения кода
|
||||||
|
* time: Для измерения времени выполнения
|
||||||
|
|
||||||
|
## Задание на лабораторную работу
|
||||||
|
|
||||||
|
**Кратко:** реализовать умножение двух больших квадратных матриц.
|
||||||
|
|
||||||
|
**Подробно:** в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * -
|
||||||
|
реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества
|
||||||
|
потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение
|
||||||
|
элементов матрицы в рамках своей зоны ответственности.
|
||||||
|
|
||||||
|
## Результаты
|
||||||
|
|
||||||
|
![Результат работы](images/results.png)
|
||||||
|
|
||||||
|
## Вывод
|
||||||
|
|
||||||
|
Результаты показывают, что для маленьких матриц последовательное умножение быстрее.
|
||||||
|
Оптимальное количество потоков близко к количеству ядер процессора. Увеличение количества потоков сверх
|
||||||
|
оптимального значения не всегда ускоряет вычисления. Параллелизм эффективнее для больших матриц.
|
||||||
|
|
||||||
|
### [Видео](https://vk.com/video212084908_456239362)
|
BIN
artamonova_tatyana_lab_5/images/results.png
Normal file
BIN
artamonova_tatyana_lab_5/images/results.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 107 KiB |
93
artamonova_tatyana_lab_5/matrix.py
Normal file
93
artamonova_tatyana_lab_5/matrix.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import time
|
||||||
|
import multiprocessing
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def multiply_matrices_sequential(matrix1, matrix2):
|
||||||
|
rows1 = len(matrix1)
|
||||||
|
cols1 = len(matrix1[0])
|
||||||
|
rows2 = len(matrix2)
|
||||||
|
cols2 = len(matrix2[0])
|
||||||
|
|
||||||
|
if cols1 != rows2:
|
||||||
|
raise ValueError("Число столбцов первой матрицы должно быть равно числу строк второй матрицы.")
|
||||||
|
|
||||||
|
result = [[0 for _ in range(cols2)] for _ in range(rows1)]
|
||||||
|
for i in range(rows1):
|
||||||
|
for j in range(cols2):
|
||||||
|
for k in range(cols1):
|
||||||
|
result[i][j] += matrix1[i][k] * matrix2[k][j]
|
||||||
|
return result
|
||||||
|
|
||||||
|
def multiply_matrices_parallel(matrix1, matrix2, num_processes):
|
||||||
|
rows1 = len(matrix1)
|
||||||
|
cols1 = len(matrix1[0])
|
||||||
|
rows2 = len(matrix2)
|
||||||
|
cols2 = len(matrix2[0])
|
||||||
|
|
||||||
|
if cols1 != rows2:
|
||||||
|
raise ValueError("Число столбцов первой матрицы должно быть равно числу строк второй матрицы.")
|
||||||
|
|
||||||
|
chunk_size = rows1 // num_processes
|
||||||
|
processes = []
|
||||||
|
results = []
|
||||||
|
|
||||||
|
with multiprocessing.Pool(processes=num_processes) as pool:
|
||||||
|
for i in range(num_processes):
|
||||||
|
start_row = i * chunk_size
|
||||||
|
end_row = (i + 1) * chunk_size if i < num_processes - 1 else rows1
|
||||||
|
p = pool.apply_async(multiply_matrix_chunk, (matrix1, matrix2, start_row, end_row))
|
||||||
|
processes.append(p)
|
||||||
|
|
||||||
|
for p in processes:
|
||||||
|
results.append(p.get())
|
||||||
|
|
||||||
|
result = [[0 for _ in range(cols2)] for _ in range(rows1)]
|
||||||
|
row_index = 0
|
||||||
|
for sub_result in results:
|
||||||
|
for row in sub_result:
|
||||||
|
result[row_index] = row
|
||||||
|
row_index += 1
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def multiply_matrix_chunk(matrix1, matrix2, start_row, end_row):
|
||||||
|
rows2 = len(matrix2)
|
||||||
|
cols2 = len(matrix2[0])
|
||||||
|
cols1 = len(matrix1[0])
|
||||||
|
result = [[0 for _ in range(cols2)] for _ in range(end_row - start_row)]
|
||||||
|
for i in range(end_row - start_row):
|
||||||
|
for j in range(cols2):
|
||||||
|
for k in range(cols1):
|
||||||
|
result[i][j] += matrix1[i + start_row][k] * matrix2[k][j]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def benchmark(matrix_size, num_processes):
|
||||||
|
matrix1 = np.random.rand(matrix_size, matrix_size).tolist()
|
||||||
|
matrix2 = np.random.rand(matrix_size, matrix_size).tolist()
|
||||||
|
|
||||||
|
try:
|
||||||
|
start_time = time.time()
|
||||||
|
sequential_result = multiply_matrices_sequential(matrix1, matrix2)
|
||||||
|
end_time = time.time()
|
||||||
|
sequential_time = end_time - start_time
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
parallel_result = multiply_matrices_parallel(matrix1, matrix2, num_processes)
|
||||||
|
end_time = time.time()
|
||||||
|
parallel_time = end_time - start_time
|
||||||
|
return sequential_time, parallel_time
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Ошибка бенчмарка с размером матрицы {matrix_size} и {num_processes} процессов: {e}")
|
||||||
|
return float('inf'), float('inf')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sizes = [100, 300, 500]
|
||||||
|
num_processes = int(input("Введите количество потоков: "))
|
||||||
|
print("Размер | Последовательно | Параллельно")
|
||||||
|
|
||||||
|
for size in sizes:
|
||||||
|
sequential_time, parallel_time = benchmark(size, num_processes)
|
||||||
|
print(f"{size:6} | {sequential_time:.4f} с \t | {parallel_time:.4f} с")
|
Loading…
Reference in New Issue
Block a user