ending
This commit is contained in:
@@ -31,54 +31,31 @@ python matrix.py
|
|||||||
|
|
||||||
```
|
```
|
||||||
matrix.py # Основной файл с реализацией алгоритмов
|
matrix.py # Основной файл с реализацией алгоритмов
|
||||||
README.md # Документация проекта
|
README.md # Документация проекта
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4. Результаты тестирования
|
## 4. Результаты тестирования
|
||||||
|
|
||||||
### Матрицы 100×100
|
На всех тестах одинаковый результат:
|
||||||
|
Детерминант при использовании множества потоков(процессов) высчитывается дольше чем при использовании строго 1 потока (главного). Это происходит из-за необходимости тратить время на выделение потоков(процессов), а также необходимости объединять результаты
|
||||||
|
|
||||||
#### Результат:
|
# Сводная таблица результатов
|
||||||
|
|
||||||
| Алгоритм | Время (сек) | Ускорение |
|
| Размер | Потоки | Время (сек) | Ускорение |
|
||||||
|----------|-------------|-----------|
|
|--------|---------|-------------|-----------|
|
||||||
| Последовательный (LU) | 0.01-0.03 | 1.00x |
|
| 100 | 1 | 0.0100 | 1.00 |
|
||||||
| Параллельный (2 процесса) | 2.5-3.5 | 0.01x |
|
| 100 | 2 | 0.3408 | 0.03 |
|
||||||
| Параллельный (4 процесса) | 1.8-2.8 | 0.01x |
|
| 100 | 4 | 0.3861 | 0.03 |
|
||||||
| Параллельный (8 процессов) | 1.5-2.5 | 0.01x |
|
| 100 | 12 | 0.5920 | 0.02 |
|
||||||
|
| 300 | 1 | 0.0783 | 1.00 |
|
||||||
|
| 300 | 2 | 1.0641 | 0.07 |
|
||||||
|
| 300 | 4 | 1.2565 | 0.06 |
|
||||||
|
| 300 | 12 | 2.1755 | 0.04 |
|
||||||
|
| 500 | 1 | 0.2195 | 1.00 |
|
||||||
|
| 500 | 2 | 3.0588 | 0.07 |
|
||||||
|
| 500 | 4 | 3.0725 | 0.07 |
|
||||||
|
| 500 | 12 | 4.7439 | 0.05 |
|
||||||
|
|
||||||
#### Вывод:
|
## 5. Видео
|
||||||
На матрицах 100×100 параллелизм **крайне неэффективен**. Overhead от создания процессов (2-3 сек) во много раз превышает время самих вычислений (0.01-0.03 сек). Последовательный LU-алгоритм работает мгновенно и является оптимальным выбором.
|
|
||||||
|
|
||||||
### Матрицы 300×300
|
ВидеоСсылка на видео работы алгоритма: [Rutube](https://rutube.ru/video/private/b655cb0028629067f79920162bf3b199/?p=l5uLlZQUmoEgv6RSAm4cVA)
|
||||||
|
|
||||||
#### Результат:
|
|
||||||
|
|
||||||
| Алгоритм | Время (сек) | Ускорение |
|
|
||||||
|----------|-------------|-----------|
|
|
||||||
| Последовательный (LU) | 0.15-0.25 | 1.00x |
|
|
||||||
| Параллельный (2 процесса) | 45-55 | 0.004x ❌ |
|
|
||||||
| Параллельный (4 процесса) | 25-35 | 0.007x ❌ |
|
|
||||||
| Параллельный (8 процессов) | 15-20 | 0.01x ❌ |
|
|
||||||
|
|
||||||
#### Вывод:
|
|
||||||
Даже на матрицах 300×300 параллелизм через разложение по строке остается **неэффективным**. LU-разложение работает за доли секунды, в то время как параллельное разложение требует десятков секунд на вычисление 300 миноров размером 299×299.
|
|
||||||
|
|
||||||
### Матрицы 500×500
|
|
||||||
|
|
||||||
#### Результат:
|
|
||||||
|
|
||||||
| Алгоритм | Время (сек) | Ускорение | Детерминант |
|
|
||||||
|----------|-------------|-----------|-------------|
|
|
||||||
| Последовательный (LU) | 0.5-0.8 | 1.00x | ~10¹⁰⁰⁰ |
|
|
||||||
| Параллельный (2 процесса) | 180-220 | 0.003x ❌ | ~10¹⁰⁰⁰ |
|
|
||||||
| Параллельный (4 процесса) | 100-130 | 0.006x ❌ | ~10¹⁰⁰⁰ |
|
|
||||||
| Параллельный (8 процессов) | 60-80 | 0.009x ❌ | ~10¹⁰⁰⁰ |
|
|
||||||
|
|
||||||
#### Вывод:
|
|
||||||
На больших матрицах 500×500 ситуация **не улучшается**. LU-разложение остается самым эффективным (менее 1 секунды), в то время как параллельное разложение по строке требует минут работы.
|
|
||||||
|
|
||||||
|
|
||||||
## 13. Видео
|
|
||||||
|
|
||||||
ВидеоСсылка на видео работы алгоритма: [Rutube](https://rutube.ru/video/private/d4dc5613005afbbe601862d54b248d36/?p=De8RTMImQZQtab3avfH2Zg)
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
import time
|
import time
|
||||||
import warnings
|
|
||||||
|
|
||||||
warnings.filterwarnings('ignore')
|
|
||||||
|
|
||||||
def sequential_determinant(matrix):
|
def sequential_determinant(matrix):
|
||||||
n = matrix.shape[0]
|
n = matrix.shape[0]
|
||||||
@@ -79,27 +76,70 @@ def parallel_determinant(matrix, num_processes = None):
|
|||||||
num_processes = mp.cpu_count()
|
num_processes = mp.cpu_count()
|
||||||
|
|
||||||
n = matrix.shape[0]
|
n = matrix.shape[0]
|
||||||
|
|
||||||
if n < 100 or num_processes == 1:
|
if n < 100 or num_processes == 1:
|
||||||
return sequential_determinant(matrix)
|
return sequential_determinant(matrix)
|
||||||
|
|
||||||
|
A = matrix.astype(np.float64).copy()
|
||||||
|
sign = 1
|
||||||
|
|
||||||
|
with mp.Pool(num_processes) as pool:
|
||||||
|
for i in range(n):
|
||||||
|
max_row = i
|
||||||
|
max_val = abs(A[i, i])
|
||||||
|
|
||||||
|
for k in range(i + 1, n):
|
||||||
|
if abs(A[k, i]) > max_val:
|
||||||
|
max_row = k
|
||||||
|
max_val = abs(A[k, i])
|
||||||
|
|
||||||
|
if max_row != i:
|
||||||
|
A[[i, max_row]] = A[[max_row, i]]
|
||||||
|
sign *= -1
|
||||||
|
|
||||||
|
if abs(A[i, i]) < 1e-15:
|
||||||
|
return 0.0, -np.inf
|
||||||
|
|
||||||
|
rows_to_update = list(range(i + 1, n))
|
||||||
|
|
||||||
|
if len(rows_to_update) >= num_processes * 2:
|
||||||
|
tasks = []
|
||||||
|
for k in rows_to_update:
|
||||||
|
tasks.append((A[k].copy(), A[i].copy(), A[k, i], A[i, i], i))
|
||||||
|
|
||||||
|
updated_rows = pool.map(_update_row_worker, tasks)
|
||||||
|
|
||||||
|
for idx, k in enumerate(rows_to_update):
|
||||||
|
A[k] = updated_rows[idx]
|
||||||
|
else:
|
||||||
|
for k in rows_to_update:
|
||||||
|
factor = A[k, i] / A[i, i]
|
||||||
|
A[k, i:] -= factor * A[i, i:]
|
||||||
|
|
||||||
|
log_abs_det = 0.0
|
||||||
|
for i in range(n):
|
||||||
|
if A[i, i] < 0:
|
||||||
|
sign *= -1
|
||||||
|
log_abs_det += np.log(abs(A[i, i]))
|
||||||
|
|
||||||
|
return sign, log_abs_det
|
||||||
|
|
||||||
|
|
||||||
|
def _update_row_worker(args):
|
||||||
|
row_k, row_i, a_ki, a_ii, i = args
|
||||||
|
|
||||||
import os
|
import os
|
||||||
old_threads = os.environ.get('OMP_NUM_THREADS', None)
|
os.environ['OMP_NUM_THREADS'] = '1'
|
||||||
os.environ['OMP_NUM_THREADS'] = str(num_processes)
|
os.environ['MKL_NUM_THREADS'] = '1'
|
||||||
os.environ['MKL_NUM_THREADS'] = str(num_processes)
|
|
||||||
os.environ['NUMEXPR_NUM_THREADS'] = str(num_processes)
|
|
||||||
|
|
||||||
result = sequential_determinant(matrix)
|
factor = a_ki / a_ii
|
||||||
|
|
||||||
if old_threads:
|
|
||||||
os.environ['OMP_NUM_THREADS'] = old_threads
|
|
||||||
else:
|
|
||||||
os.environ.pop('OMP_NUM_THREADS', None)
|
|
||||||
|
|
||||||
return result
|
row_k[i:] -= factor * row_i[i:]
|
||||||
|
|
||||||
|
return row_k
|
||||||
|
|
||||||
|
|
||||||
def generate_stable_matrix(size: int, scale: float = 1.0) -> np.ndarray:
|
def generate_stable_matrix(size, scale = 1.0) -> np.ndarray:
|
||||||
np.random.seed(13)
|
np.random.seed(13)
|
||||||
|
|
||||||
random_matrix = np.random.randn(size, size)
|
random_matrix = np.random.randn(size, size)
|
||||||
@@ -150,10 +190,6 @@ def benchmark(sizes, thread_counts):
|
|||||||
print(f" Детерминант: {det_seq:.6e}")
|
print(f" Детерминант: {det_seq:.6e}")
|
||||||
print(f" Sign: {sign_seq}, Log|det|: {logdet_seq:.6f}")
|
print(f" Sign: {sign_seq}, Log|det|: {logdet_seq:.6f}")
|
||||||
|
|
||||||
if logdet_numpy is not None:
|
|
||||||
log_error = abs(logdet_seq - logdet_numpy)
|
|
||||||
print(f" Ошибка Log|det|: {log_error:.10f}")
|
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'size': size,
|
'size': size,
|
||||||
'threads': 1,
|
'threads': 1,
|
||||||
@@ -174,18 +210,12 @@ def benchmark(sizes, thread_counts):
|
|||||||
det_par = to_float(sign_par, logdet_par)
|
det_par = to_float(sign_par, logdet_par)
|
||||||
|
|
||||||
speedup = seq_time / par_time if par_time > 0 else 0
|
speedup = seq_time / par_time if par_time > 0 else 0
|
||||||
efficiency = speedup / num_threads * 100
|
|
||||||
|
|
||||||
print(f"Параллельный алгоритм ({num_threads} потоков):")
|
print(f"Параллельный алгоритм ({num_threads} потоков):")
|
||||||
print(f" Время: {par_time:.4f} сек")
|
print(f" Время: {par_time:.4f} сек")
|
||||||
print(f" Детерминант: {det_par:.6e}")
|
print(f" Детерминант: {det_par:.6e}")
|
||||||
print(f" Ускорение: {speedup:.2f}x")
|
print(f" Ускорение: {speedup:.2f}x")
|
||||||
print(f" Эффективность: {efficiency:.1f}%")
|
|
||||||
|
|
||||||
if logdet_numpy is not None:
|
|
||||||
log_error = abs(logdet_par - logdet_numpy)
|
|
||||||
print(f" Ошибка Log|det|: {log_error:.10f}")
|
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'size': size,
|
'size': size,
|
||||||
'threads': num_threads,
|
'threads': num_threads,
|
||||||
@@ -210,26 +240,8 @@ if __name__ == "__main__":
|
|||||||
print("СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ")
|
print("СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ")
|
||||||
print("=" * 80)
|
print("=" * 80)
|
||||||
print()
|
print()
|
||||||
print(f"{'Размер':<10} {'Потоки':<10} {'Время (сек)':<15} {'Ускорение':<12} {'Эффективность'}")
|
print(f"{'Размер':<10} {'Потоки':<10} {'Время (сек)':<15} {'Ускорение':<12}")
|
||||||
print("-" * 80)
|
print("-" * 80)
|
||||||
|
|
||||||
for r in results:
|
for r in results:
|
||||||
efficiency = (r['speedup'] / r['threads'] * 100) if r['threads'] > 1 else 100
|
print(f"{r['size']:<10} {r['threads']:<10} {r['time']:<15.4f} {r['speedup']:<12.2f}")
|
||||||
print(f"{r['size']:<10} {r['threads']:<10} {r['time']:<15.4f} {r['speedup']:<12.2f} {efficiency:>6.1f}%")
|
|
||||||
|
|
||||||
print("\n" + "=" * 80)
|
|
||||||
print("АНАЛИЗ ПРОИЗВОДИТЕЛЬНОСТИ")
|
|
||||||
print("=" * 80)
|
|
||||||
print()
|
|
||||||
|
|
||||||
for size in sizes:
|
|
||||||
size_results = [r for r in results if r['size'] == size]
|
|
||||||
if len(size_results) > 1:
|
|
||||||
seq_time = size_results[0]['time']
|
|
||||||
best_parallel = min(size_results[1:], key=lambda x: x['time'])
|
|
||||||
|
|
||||||
print(f"Матрица {size}x{size}:")
|
|
||||||
print(f" Последовательное время: {seq_time:.4f} сек")
|
|
||||||
print(f" Лучшее параллельное: {best_parallel['time']:.4f} сек ({best_parallel['threads']} потоков)")
|
|
||||||
print(f" Максимальное ускорение: {best_parallel['speedup']:.2f}x")
|
|
||||||
print()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user