import numpy as np
from multiprocessing import Pool
import time


def determinant_block(matrix_block):
    return np.linalg.det(matrix_block)


def determinant_parallel(matrix, num_processes):
    size = matrix.shape[0]
    step = size // num_processes

    pool = Pool(processes=num_processes)
    blocks = []
    for i in range(0, size, step):
        blocks.append(matrix[i:i+step, i:i+step])

    dets = pool.map(determinant_block, blocks)
    return np.prod(dets)


if __name__ == "__main__":
    sizes = [100, 300, 500]
    processes = [2, 4, 8]

    for size in sizes:
        matrix = np.random.rand(size, size)

        for p in processes:
            start = time.time()
            det = determinant_parallel(matrix, p)
            end = time.time()
            print(f"{size}x{size} matrix with {p} processes took {end - start:.5f} secs")

        start = time.time()
        det_seq = determinant_block(matrix)
        end = time.time()
        print(f"{size}x{size} matrix sequential took {end - start:.5f} secs")