Merge pull request 'basharin_sevastyan_lab_5 is ready' (#26) from basharin_sevastyan_lab_5 into main
Reviewed-on: http://student.git.athene.tech/Alexey/DAS_2023_1/pulls/26
This commit is contained in:
commit
afd81bb6c1
112
basharin_sevastyan_lab_5/README.md
Normal file
112
basharin_sevastyan_lab_5/README.md
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
## Лабораторная работа 5
|
||||||
|
|
||||||
|
### Задание
|
||||||
|
Реализовать умножение двух больших квадратных матриц
|
||||||
|
|
||||||
|
### Ход выполнения
|
||||||
|
- Реализовать алгоритм перемножение матриц для потокового выполнения
|
||||||
|
- Адаптировать алгоритм для параллельного выполнения:
|
||||||
|
- Разделить данные на чанки, сохранив корректность вычислений
|
||||||
|
|
||||||
|
### Как запустить
|
||||||
|
В терминале, находясь в корневой директории файлов проекта, выполнить команду:
|
||||||
|
```
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
Результат будет выведен в терминале.
|
||||||
|
|
||||||
|
### Технологии
|
||||||
|
- `numpy`: библиотека для работы с многомерными массивами и матрицами в Python.
|
||||||
|
- `multiprocessing`: модуль Python, предоставляющий возможность создания и управления процессами, что позволяет реализовать параллельные вычисления.
|
||||||
|
|
||||||
|
### Описание работы
|
||||||
|
#### Обычный алгоритм
|
||||||
|
```python
|
||||||
|
def sequential_multiply(A, B):
|
||||||
|
# Определение размеров матриц A и B
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
rows_B = len(B)
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
# Проверка совместимости матриц для умножения
|
||||||
|
if cols_A != rows_B:
|
||||||
|
print("Cannot multiply matrices")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Создание матрицы C, результат умножения A на B
|
||||||
|
C = [[0 for row in range(cols_B)] for col in range(rows_A)]
|
||||||
|
|
||||||
|
# Выполнение умножения матриц
|
||||||
|
for i in range(rows_A):
|
||||||
|
for j in range(cols_B):
|
||||||
|
for k in range(cols_A):
|
||||||
|
C[i][j] += A[i][k] * B[k][j]
|
||||||
|
|
||||||
|
return C
|
||||||
|
```
|
||||||
|
Этапы:
|
||||||
|
1. Определение размеров матриц: Получаются размеры матриц A и B (число строк и столбцов каждой матрицы).
|
||||||
|
2. Проверка совместимости матриц: Проверяется, можно ли умножить матрицы A и B. Умножение возможно, если количество столбцов матрицы A равно количеству строк матрицы B.
|
||||||
|
3. Создание матрицы-результата: Создается матрица C, которая будет содержать результат умножения матриц A и B. Размеры матрицы C определяются числом строк матрицы A и числом столбцов матрицы B.
|
||||||
|
4. Умножение матриц: Вложенные циклы используются для умножения каждого элемента матрицы C. Внешний цикл итерируется по строкам матрицы A, второй цикл по столбцам матрицы B, а третий цикл выполняет суммирование произведений элементов соответствующих ячеек для получения значения элемента в матрице C.
|
||||||
|
5. Возврат результата: Возвращается матрица C, которая является результатом умножения матриц A и B.
|
||||||
|
|
||||||
|
#### Параллельный алгоритм
|
||||||
|
```python
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
def parallel_multiply(A, B, num_processes):
|
||||||
|
# Определение размеров матриц A и B
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
rows_B = len(B)
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
# Проверка совместимости матриц для умножения
|
||||||
|
if cols_A != rows_B:
|
||||||
|
print("Cannot multiply matrices")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Создание матрицы C, результат умножения A на B
|
||||||
|
C = [[0 for row in range(cols_B)] for col in range(rows_A)]
|
||||||
|
|
||||||
|
# Разделение работы между процессами
|
||||||
|
chunk_size = int(rows_A / num_processes)
|
||||||
|
|
||||||
|
# Создание процессов
|
||||||
|
processes = []
|
||||||
|
for i in range(num_processes):
|
||||||
|
start = chunk_size * i
|
||||||
|
end = chunk_size * (i + 1) if i < num_processes - 1 else rows_A
|
||||||
|
|
||||||
|
# Запуск процесса с функцией perform_multiplication
|
||||||
|
p = multiprocessing.Process(target=perform_multiplication, args=(A, B, C, start, end))
|
||||||
|
processes.append(p)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
# Ожидание завершения всех процессов
|
||||||
|
for p in processes:
|
||||||
|
p.join()
|
||||||
|
|
||||||
|
return C
|
||||||
|
|
||||||
|
def perform_multiplication(A, B, C, start, end):
|
||||||
|
# Умножение подматрицы A на матрицу B
|
||||||
|
for i in range(start, end):
|
||||||
|
for j in range(len(B[0])):
|
||||||
|
for k in range(len(A[0])):
|
||||||
|
C[i][j] += A[i][k] * B[k][j]
|
||||||
|
```
|
||||||
|
*Первые три этапа похожи на обычный алгоритм, поэтому не имеет смысла их описывать.*
|
||||||
|
Этапы:
|
||||||
|
1. Разделение работы между процессами: Матрица A разбивается на несколько частей, и для каждой части создается отдельный процесс.
|
||||||
|
2. Создание и запуск процессов: Для каждой части матрицы A создается процесс, который вызывает функцию perform_multiplication. Каждый процесс работает с своим подмножеством данных.
|
||||||
|
3. Ожидание завершения всех процессов: Главный процесс ждет завершения работы всех созданных процессов с помощью метода join().
|
||||||
|
4. Возврат результата: Возвращается матрица C, которая является результатом умножения матриц A и B.
|
||||||
|
|
||||||
|
### Результат работы
|
||||||
|
![](res.png "")
|
||||||
|
|
||||||
|
### Видео
|
||||||
|
https://youtu.be/XIEENJAUPNY
|
78
basharin_sevastyan_lab_5/main.py
Normal file
78
basharin_sevastyan_lab_5/main.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import multiprocessing
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def sequential_multiply(A, B):
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
rows_B = len(B)
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
if cols_A != rows_B:
|
||||||
|
print("Cannot multiply matrices")
|
||||||
|
return
|
||||||
|
|
||||||
|
C = [[0 for row in range(cols_B)] for col in range(rows_A)]
|
||||||
|
|
||||||
|
for i in range(rows_A):
|
||||||
|
for j in range(cols_B):
|
||||||
|
for k in range(cols_A):
|
||||||
|
C[i][j] += A[i][k] * B[k][j]
|
||||||
|
|
||||||
|
return C
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_multiply(A, B, num_processes):
|
||||||
|
rows_A = len(A)
|
||||||
|
cols_A = len(A[0])
|
||||||
|
rows_B = len(B)
|
||||||
|
cols_B = len(B[0])
|
||||||
|
|
||||||
|
if cols_A != rows_B:
|
||||||
|
print("Cannot multiply matrices")
|
||||||
|
return
|
||||||
|
|
||||||
|
C = [[0 for row in range(cols_B)] for col in range(rows_A)]
|
||||||
|
|
||||||
|
chunk_size = int(rows_A / num_processes)
|
||||||
|
|
||||||
|
processes = []
|
||||||
|
for i in range(num_processes):
|
||||||
|
start = chunk_size * i
|
||||||
|
end = chunk_size * (i + 1) if i < num_processes - 1 else rows_A
|
||||||
|
|
||||||
|
p = multiprocessing.Process(target=perform_multiplication, args=(A, B, C, start, end))
|
||||||
|
processes.append(p)
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
for p in processes:
|
||||||
|
p.join()
|
||||||
|
|
||||||
|
return C
|
||||||
|
|
||||||
|
|
||||||
|
def perform_multiplication(A, B, C, start, end):
|
||||||
|
for i in range(start, end):
|
||||||
|
for j in range(len(B[0])):
|
||||||
|
for k in range(len(A[0])):
|
||||||
|
C[i][j] += A[i][k] * B[k][j]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
matrix_sizes = [100, 300, 500]
|
||||||
|
num_processes = 4 #int(input('Введите количество потоков: '))
|
||||||
|
|
||||||
|
for n in matrix_sizes:
|
||||||
|
A = np.random.randint(10, size=(n, n))
|
||||||
|
B = np.random.randint(10, size=(n, n))
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
|
sequential_result = sequential_multiply(A, B)
|
||||||
|
end = time.time()
|
||||||
|
print(f"Sequential {n}x{n} time: {end - start}")
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
|
parallel_result = parallel_multiply(A, B, num_processes)
|
||||||
|
end = time.time()
|
||||||
|
print(f"Parallel {n}x{n} time: {end - start}")
|
Loading…
Reference in New Issue
Block a user