Compare commits
1 Commits
main
...
kochkareva
Author | SHA1 | Date | |
---|---|---|---|
|
74c65bfcde |
73
kochkareva_elizaveta_lab_6/README.md
Normal file
73
kochkareva_elizaveta_lab_6/README.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
# Лабораторная работа 6.
|
||||||
|
|
||||||
|
### Задание
|
||||||
|
|
||||||
|
**Задачи**:
|
||||||
|
|
||||||
|
Реализовать нахождение детерминанта квадратной матрицы. Сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять нахождение отдельной группы множителей.
|
||||||
|
|
||||||
|
|
||||||
|
### Как запустить лабораторную работу
|
||||||
|
В директории с файлом характеристик docker-compose.yaml выполнить команду:
|
||||||
|
```
|
||||||
|
docker-compose -f docker-compose.yaml up
|
||||||
|
```
|
||||||
|
|
||||||
|
### Описание лабораторной работы
|
||||||
|
|
||||||
|
Для реализации параллельного нахождения детерминанта квадратной матрицы с использованием многопоточности создадим несколько функций:
|
||||||
|
|
||||||
|
1. Функция `calculate_determinant(args)`
|
||||||
|
|
||||||
|
Данная функция принимает матрицу и номер элемента, по которому ищется минор. Если `i` нечетное число, множитель умножается на -1.
|
||||||
|
Удаляет первую строку из `matrix` с помощью функции `np.delete(matrix, 0, axis=0)`.
|
||||||
|
Удаляет столбец `i` из `matrix` с помощью функции `np.delete(matrix, i, axis=1)`.
|
||||||
|
Возвращает определитель полученной подматрицы, умноженный на множитель.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def calculate_determinant(args):
|
||||||
|
matrix, i = args
|
||||||
|
multiplier = matrix[0][i]
|
||||||
|
if i % 2 != 0:
|
||||||
|
multiplier *= -1
|
||||||
|
matrix = np.delete(matrix, 0, axis=0)
|
||||||
|
submatrix = np.delete(matrix, i, axis=1)
|
||||||
|
return np.linalg.det(submatrix) * multiplier
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Функция `parallel_determinant(matrix, parallel)`
|
||||||
|
|
||||||
|
Данная функция принимает матрицу, для которой нужно вычислить определитель, и флаг, указывающий, следует ли использовать параллельное вычисление. Далее вычисляется размер матрицы `n` с `помощью matrix.shape[0]`. Если флаг указывает на использование параллельного вычисления, создается пул процессов с `n` процессами с помощью `Pool(processes=n)`. Затем создается цикл по значениям от `0` до `n`.
|
||||||
|
Для каждого значения `i` добавляет в список `results` результат выполнения функции `calculate_determinant` с аргументами `matrix` и `i`. Затем закрывается пул процессов и ожидается завершения всех процессов с помощью `pool.close()` и `pool.join()`. Далее суммируются все значения из списка results с помощью `np.sum([res.get() for res in results])`, сохраняет результат в переменную result и также вычисляется затраченное время на вычисление определителя.
|
||||||
|
|
||||||
|
3. Функция `test(parallel)`
|
||||||
|
|
||||||
|
Данная функция принимает значение флага, указывающего на использование параллельного или обычного вычисления. Также создает матрицу mx размером 3x3 и выполняет вычисление определителя матрицы mx с помощью функции `parallel_determinant(mx, parallel)`.
|
||||||
|
|
||||||
|
4. Функции `matrix10x10(parallel)`, `matrix25x25(parallel)` и `matrix50x50(parallel)`
|
||||||
|
|
||||||
|
Т.к. на моем устройстве не возможно вычислять детерминат матрицы размером более 100х100, то вместо использования матриц размером 100x100, 300x300, 500x500 элементов были созданы матрицы 10х10, 25х25, 50х50.
|
||||||
|
|
||||||
|
В функциях `matrix10x10(parallel)`, `matrix25x25(parallel)` и `matrix50x50(parallel)` принимается аргумент `parallel`, указывающий, следует ли использовать параллельное вычисление. Создаются матрицы размером 10x10, 25x25 и 50x50 со случайными целочисленными значениями от 0 до 100. И выполяются вычисления определителя для каждой матрицы с помощью функции `parallel_determinant`.
|
||||||
|
|
||||||
|
#### Результаты выполнения последовательного и параллельного алгоритма на вычисление детерминанта квадратных матриц 10х10, 25х25, 50х50.
|
||||||
|
|
||||||
|
Результат вычисления детерминанта матрицы 10х10:
|
||||||
|
|
||||||
|
![Результат вычисления детерминанта матрицы 10х10:](matrix10x10.jpg)
|
||||||
|
|
||||||
|
Результат вычисления детерминанта матрицы 25х25:
|
||||||
|
|
||||||
|
![Результат вычисления детерминанта матрицы 25х25:](matrix25x25.jpg)
|
||||||
|
|
||||||
|
Результат вычисления детерминанта матрицы 50х50:
|
||||||
|
|
||||||
|
![Результат перемножения матриц 500х500](matrix50x50.jpg)
|
||||||
|
|
||||||
|
Таким образом, можно сделать вывод о том, что вычисления обычным алгоритмом выполняются быстрее, чем при использовании параллельного способа нахождения детерминанта. Если точность результата является наиболее приоритетным фактором, то использование параллельного способа может быть предпочтительным. В случае, когда время выполнения играет решающую роль, обычный алгоритм может быть более эффективным выбором. Кроме того, для дальнейшего улучшения производительности вычислений можно рассмотреть возможность оптимизации параллельного способа нахождения детерминанта, например, с использованием более эффективных алгоритмов или распределения вычислений на более мощные вычислительные узлы.
|
||||||
|
|
||||||
|
|
||||||
|
### Видео
|
||||||
|
|
||||||
|
https://disk.yandex.ru/i/i8qDyMhn6nCk9A
|
79
kochkareva_elizaveta_lab_6/main.py
Normal file
79
kochkareva_elizaveta_lab_6/main.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_determinant(args):
|
||||||
|
matrix, i = args
|
||||||
|
multiplier = matrix[0][i]
|
||||||
|
if i % 2 != 0:
|
||||||
|
multiplier *= -1
|
||||||
|
matrix = np.delete(matrix, 0, axis=0)
|
||||||
|
submatrix = np.delete(matrix, i, axis=1)
|
||||||
|
return np.linalg.det(submatrix) * multiplier
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_determinant(matrix, parallel):
|
||||||
|
n = matrix.shape[0]
|
||||||
|
if parallel:
|
||||||
|
pool = Pool(processes=n)
|
||||||
|
results = []
|
||||||
|
start_time = time.time()
|
||||||
|
for i in range(n):
|
||||||
|
results.append(pool.apply_async(calculate_determinant, args=((matrix, i),)))
|
||||||
|
pool.close()
|
||||||
|
pool.join()
|
||||||
|
result = np.sum([res.get() for res in results])
|
||||||
|
end_time = time.time()
|
||||||
|
else:
|
||||||
|
start_time = time.time()
|
||||||
|
result = np.linalg.det(matrix)
|
||||||
|
end_time = time.time()
|
||||||
|
execution_time = end_time - start_time
|
||||||
|
return result, execution_time
|
||||||
|
|
||||||
|
|
||||||
|
def test(parallel):
|
||||||
|
mx = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
||||||
|
result = parallel_determinant(mx, parallel)
|
||||||
|
print(f"Определитель матрицы: {result[0]}")
|
||||||
|
print(f"Время выполнения: {result[1]} сек.")
|
||||||
|
|
||||||
|
|
||||||
|
def matrix10x10(parallel):
|
||||||
|
mx = np.random.randint(0, 100, size=(10, 10))
|
||||||
|
result = parallel_determinant(mx, parallel)
|
||||||
|
print(f"Определитель матрицы: {result[0]}")
|
||||||
|
print(f"Время выполнения: {result[1]} сек.")
|
||||||
|
|
||||||
|
|
||||||
|
def matrix25x25(parallel):
|
||||||
|
mx = np.random.randint(0, 100, size=(25, 25))
|
||||||
|
result = parallel_determinant(mx, parallel)
|
||||||
|
print(f"Определитель матрицы: {result[0]}")
|
||||||
|
print(f"Время выполнения: {result[1]} сек.")
|
||||||
|
|
||||||
|
|
||||||
|
def matrix50x50(parallel):
|
||||||
|
mx = np.random.randint(0, 100, size=(50, 50))
|
||||||
|
result = parallel_determinant(mx, parallel)
|
||||||
|
print(f"Определитель матрицы: {result[0]}")
|
||||||
|
print(f"Время выполнения: {result[1]} сек.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# print("Матрица 10x10:")
|
||||||
|
# print("Результат нахождения детерминанта параллельно:")
|
||||||
|
# matrix10x10(parallel=True)
|
||||||
|
# print("Результат нахождения детерминанта обычным способом:")
|
||||||
|
# matrix10x10(parallel=False)
|
||||||
|
# print("Матрица 25x25:")
|
||||||
|
# print("Результат нахождения детерминанта параллельно:")
|
||||||
|
# matrix25x25(parallel=True)
|
||||||
|
# print("Результат нахождения детерминанта обычным способом:")
|
||||||
|
# matrix25x25(parallel=False)
|
||||||
|
print("Матрица 50x50:")
|
||||||
|
print("Результат нахождения детерминанта параллельно:")
|
||||||
|
matrix50x50(parallel=True)
|
||||||
|
print("Результат нахождения детерминанта обычным способом:")
|
||||||
|
matrix50x50(parallel=False)
|
BIN
kochkareva_elizaveta_lab_6/matrix10x10.jpg
Normal file
BIN
kochkareva_elizaveta_lab_6/matrix10x10.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
BIN
kochkareva_elizaveta_lab_6/matrix25x25.jpg
Normal file
BIN
kochkareva_elizaveta_lab_6/matrix25x25.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
BIN
kochkareva_elizaveta_lab_6/matrix50x50.jpg
Normal file
BIN
kochkareva_elizaveta_lab_6/matrix50x50.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Loading…
Reference in New Issue
Block a user