import random
import time
import multiprocessing
import numpy as np

# Генерация матрицы
def generate_matrix(size):
    return [[random.randint(0, 10) for _ in range(size)] for _ in range(size)]

# Умножение одной строки
def multiply_row(i, A, B, result):
    size = len(A)
    for j in range(size):
        for k in range(size):
            result[i][j] += A[i][k] * B[k][j]

# параллельное умножение матриц с помощью multiprocessing
def parallel_matrix_multiply(A, B, num_processes):
    size = len(A)
    result = [[0] * size for _ in range(size)]
    
    with multiprocessing.Pool(processes=num_processes) as pool:
        pool.starmap(multiply_row, [(i, A, B, result) for i in range(size)])
    
    return result

# Замер времени на умножение
def benchmark(size, num_processes=1):
    A = generate_matrix(size)
    B = generate_matrix(size)

    start_time = time.time()
    parallel_matrix_multiply(A, B, num_processes)
    par_time = time.time() - start_time

    return par_time

def main():
    # Размеры матриц
    matrix_sizes = [100, 300, 500]  
    # Количество потоков
    num_processes_list = [1, 2, 4, 6, 8]
    # Таблица с бенчмарками
    print("-*" * 40)
    print(f"{'Количество потоков':<20}{'|100x100 (сек.)':<20}{'|300x300 (сек.)':<20}{'|500x500 (сек.)'}")
    print("-*" * 40)
    
    for num_processes in num_processes_list:
        row = f"{num_processes:<20}"
        
        for size in matrix_sizes:
            par_time = benchmark(size, num_processes)
            row += f"|{par_time:.4f}".ljust(20)
        print(row)
        print("-*" * 40)

if __name__ == "__main__":
    main()