import multiprocessing
import time
from time import time

import numpy as np


def matrix_multi(first, second, res, start_i, stop_i, size):
    for i in range(start_i, stop_i):
        for j in range(size):
            res[i][j] = 0
            for k in range(size):
                res[i][j] += first[i][k] * second[k][j]


def do(first, second, size, threads):
    offset = int(size / threads)
    offset_last = size % threads + offset

    processes = []
    res = np.zeros((size, size))
    start_test = time()
    for i in range(threads):
        start_ = i * offset
        stop_ = start_ + offset_last if i == threads - 1 else start_ + offset

        process = multiprocessing.Process(target=matrix_multi, args=(first, second, res, start_, stop_, size))
        processes.append(process)
        process.start()

    for p in processes:
        p.join()
    stop_test = time()
    print(f'{size}x{size}, time: {stop_test - start_test}')


if __name__ == "__main__":
    sizes = [100, 300, 500]
    threads_counts = [1, 4, 6, 8, 12]
    for threads in threads_counts:
        print('-------------------------------------------------')
        print(f'Threads:{threads}')
        for n in sizes:
            first_matrix = np.random.randint(3, size=(n, n))
            second_matrix = np.random.randint(3, size=(n, n))
            if threads == 1:
                res = np.zeros((n, n))
                start = time()
                matrix_multi(first_matrix, second_matrix, res, 0, n, n)
                stop = time()
                print(f'{n}x{n}, time: {stop - start}')
            else:
                do(first_matrix, second_matrix, n, threads)

        print('-------------------------------------------------')