import multiprocessing
import numpy as np
import time


def sequential_multiply(A, B):
    rows_A = len(A)
    cols_A = len(A[0])
    rows_B = len(B)
    cols_B = len(B[0])

    if cols_A != rows_B:
        print("Cannot multiply matrices")
        return

    C = [[0 for row in range(cols_B)] for col in range(rows_A)]

    for i in range(rows_A):
        for j in range(cols_B):
            for k in range(cols_A):
                C[i][j] += A[i][k] * B[k][j]

    return C


def parallel_multiply(A, B, num_processes):
    rows_A = len(A)
    cols_A = len(A[0])
    rows_B = len(B)
    cols_B = len(B[0])

    if cols_A != rows_B:
        print("Cannot multiply matrices")
        return

    C = [[0 for row in range(cols_B)] for col in range(rows_A)]

    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))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

    return C


def perform_multiplication(A, B, C, start, end):
    for i in range(start, end):
        for j in range(len(B[0])):
            for k in range(len(A[0])):
                C[i][j] += A[i][k] * B[k][j]


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

    for n in matrix_sizes:
        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"Sequential {n}x{n} time: {end - start}")

        start = time.time()
        parallel_result = parallel_multiply(A, B, num_processes)
        end = time.time()
        print(f"Parallel {n}x{n} time: {end - start}")