artamonova_tatyana_lab_6 is ready
This commit is contained in:
parent
131dc39f6c
commit
e0a2b5991a
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