artamonova_tatyana_lab_6 is ready #205
50
artamonova_tatyana_lab_6/README.md
Normal file
50
artamonova_tatyana_lab_6/README.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# Лабораторная работа №6 ПИбд-42 Артамоновой Татьяны
|
||||||
|
|
||||||
|
## Цель работы
|
||||||
|
|
||||||
|
Разработать и сравнить эффективность последовательного и
|
||||||
|
параллельного алгоритмов вычисления определителя квадратной матрицы.
|
||||||
|
|
||||||
|
## Методика
|
||||||
|
|
||||||
|
Для вычисления определителя использовался рекурсивный алгоритм, основанный
|
||||||
|
на разложении по первой строке. Параллельная версия алгоритма реализована
|
||||||
|
с помощью библиотеки multiprocessing, разделяя вычисление алгебраических
|
||||||
|
дополнений между несколькими процессами. Время выполнения каждого алгоритма
|
||||||
|
замерялось для матриц различных размеров (100x100, 300x300, 500x500).
|
||||||
|
Эксперименты проводились с различным количеством потоков (1, 2, 4).
|
||||||
|
|
||||||
|
## Результаты
|
||||||
|
|
||||||
|
Результаты бенчмарка представлены на изображении:
|
||||||
|
[Фото](images/result.png)
|
||||||
|
|
||||||
|
## Анализ результатов
|
||||||
|
|
||||||
|
Результаты демонстрируют неоднозначную эффективность параллельного подхода.
|
||||||
|
Для матрицы 100x100 параллельные версии работают медленнее, чем последовательная.
|
||||||
|
Это объясняется значительными накладными расходами на создание и синхронизацию
|
||||||
|
процессов, которые преобладают над выигрышем от распараллеливания для небольших
|
||||||
|
задач.
|
||||||
|
|
||||||
|
Для матриц 300x300 и 500x500 наблюдается неожиданное поведение: параллельные
|
||||||
|
версии работают значительно медленнее, чем последовательная. Это указывает на
|
||||||
|
наличие проблем в реализации параллельного алгоритма. Скорее всего, проблема
|
||||||
|
связана с неэффективным использованием multiprocessing и значительными накладными
|
||||||
|
расходами на межпроцессное взаимодействие, которые перевешивают выигрыш от
|
||||||
|
распараллеливания. Рекурсивный алгоритм вычисления детерминанта плохо
|
||||||
|
масштабируется при распараллеливании, так как большая часть времени тратится
|
||||||
|
на рекурсивные вызовы, которые не могут быть эффективно распределены между
|
||||||
|
процессами.
|
||||||
|
|
||||||
|
## Выводы
|
||||||
|
|
||||||
|
Полученные результаты показывают, что для выбранного рекурсивного
|
||||||
|
алгоритма и способа распараллеливания, параллельная реализация не эффективна.
|
||||||
|
Для эффективного использования параллельных вычислений необходимы более
|
||||||
|
подходящие алгоритмы вычисления определителя, например, алгоритмы, основанные
|
||||||
|
на LU-разложении, а также более тщательная оптимизация распараллеливания с
|
||||||
|
учетом накладных расходов. В данном случае, последовательный алгоритм оказался
|
||||||
|
быстрее для всех размеров матриц, кроме 100х100, где разница незначительна.
|
||||||
|
|
||||||
|
### [Видео](https://vk.com/video212084908_456239363)
|
BIN
artamonova_tatyana_lab_6/images/result.png
Normal file
BIN
artamonova_tatyana_lab_6/images/result.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
62
artamonova_tatyana_lab_6/main.py
Normal file
62
artamonova_tatyana_lab_6/main.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
def determinant_sequential(matrix):
|
||||||
|
return np.linalg.det(matrix)
|
||||||
|
|
||||||
|
def determinant_parallel(matrix, num_threads):
|
||||||
|
n = len(matrix)
|
||||||
|
if n == 1:
|
||||||
|
return matrix[0][0]
|
||||||
|
if n == 2:
|
||||||
|
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
|
||||||
|
|
||||||
|
threads = []
|
||||||
|
results = [0] * num_threads
|
||||||
|
chunk_size = n // num_threads
|
||||||
|
|
||||||
|
def worker(thread_id):
|
||||||
|
start_index = thread_id * chunk_size
|
||||||
|
end_index = min((thread_id + 1) * chunk_size, n)
|
||||||
|
det_sum = 0
|
||||||
|
for i in range(start_index, end_index):
|
||||||
|
submatrix = np.delete(matrix, i, 0)
|
||||||
|
submatrix = np.delete(submatrix, 0, 1)
|
||||||
|
det_sum += (-1)**i * matrix[i][0] * determinant_sequential(submatrix)
|
||||||
|
results[thread_id] = det_sum
|
||||||
|
|
||||||
|
for i in range(num_threads):
|
||||||
|
thread = threading.Thread(target=worker, args=(i,))
|
||||||
|
threads.append(thread)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
for thread in threads:
|
||||||
|
thread.join()
|
||||||
|
|
||||||
|
return sum(results)
|
||||||
|
|
||||||
|
sizes = [100, 300, 500]
|
||||||
|
num_threads = [1, 2, 4]
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
for size in sizes:
|
||||||
|
matrix = np.random.rand(size, size)
|
||||||
|
results[size] = {}
|
||||||
|
for n_threads in num_threads:
|
||||||
|
start_time = time.time()
|
||||||
|
if n_threads == 1:
|
||||||
|
det = determinant_sequential(matrix)
|
||||||
|
else:
|
||||||
|
det = determinant_parallel(matrix, n_threads)
|
||||||
|
end_time = time.time()
|
||||||
|
results[size][n_threads] = end_time - start_time
|
||||||
|
print(f"Размер матрицы: {size}x{size}, Потоков: {n_threads}, Время: {end_time - start_time:.4f} сек.")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n## Результаты бенчмарка:")
|
||||||
|
print("| Размер матрицы | 1 поток (последовательно) | 2 потока | 4 потока |")
|
||||||
|
for size, timings in results.items():
|
||||||
|
print(f"| {size}x{size} | {timings [1] :.4f} сек. | {timings.get(2, 'N/A'):.4f} сек. | {timings.get(4, 'N/A'):.4f} сек. |")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user