import multiprocessing
import numpy as np
import time

def sequential_multiply(A, B):
    # Последовательное умножение матриц
    return np.dot(A, B)

def parallel_multiply(A, B, num_processes):
    rows_A = A.shape[0]
    cols_B = B.shape[1]

    # Используем Array для совместного использования памяти
    C = multiprocessing.Array('d', rows_A * cols_B)  # 'd' для double

    chunk_size = int(rows_A / num_processes)
    processes = []

    for i in range(num_processes):
        start = chunk_size * i
        end = chunk_size * (i + 1) if i < num_processes - 1 else rows_A

        # Запускаем процесс для умножения
        p = multiprocessing.Process(target=perform_multiplication, args=(A, B, C, start, end, rows_A, cols_B))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

    # Преобразуем C в 2D массив NumPy для удобства
    return np.frombuffer(C.get_obj()).reshape((rows_A, cols_B))

def perform_multiplication(A, B, C, start, end, rows_A, cols_B):
    # Умножение строк матрицы A на столбцы матрицы B
    for i in range(start, end):
        for j in range(cols_B):
            C[i * cols_B + j] = np.dot(A[i, :], B[:, j])

if __name__ == "__main__":
    matrix_sizes = [100, 300, 500]
    num_processes = int(input('Введите количество потоков: '))

    for n in matrix_sizes:
        # Генерация случайных матриц A и B
        A = np.random.randint(10, size=(n, n))
        B = np.random.randint(10, size=(n, n))

        # Бенчмарк для последовательного умножения
        start = time.time()
        sequential_result = sequential_multiply(A, B)
        end = time.time()
        print(f"Последовательное умножение {n}x{n}: {end - start:.6f} секунд")

        # Бенчмарк для параллельного умножения
        start = time.time()
        parallel_result = parallel_multiply(A, B, num_processes)
        end = time.time()
        print(f"Параллельное умножение {n}x{n}: {end - start:.6f} секунд")

        # Проверка совпадения результатов
        assert np.array_equal(sequential_result, parallel_result), "Результаты не совпадают!"