import math
from multiprocessing import Pool
import numpy as np
from datetime import datetime


# Метод по умножение определенных строк 1й матрицы на столбцы 2й матрицы
def work(start, end, fst, sec):
    result = []
    for i1 in range(start, end):
        str = np.zeros(len(sec[0]))
        for j2 in range(0, len(sec[0])):
            mul = np.zeros(len(sec[0]))
            for i2 in range(0, len(sec)):
                mul[i2] = fst[i1][i2] * sec[i2][j2]
            str[j2] = np.sum(mul)
        result.append(str.tolist())

    return result


if __name__ == '__main__':

    sizes = [100, 300]
    threads_counts = [1, 2, 4, 8]

    for size_arrays in sizes:

        fst = np.random.randint(1, 30, size=(size_arrays, size_arrays))
        sec = np.random.randint(1, 30, size=(size_arrays, size_arrays))
        result = np.ones((size_arrays, size_arrays,), dtype='int32')

        for thread_count in threads_counts:
            step = math.floor(size_arrays / thread_count)
            remaining_lines = size_arrays % thread_count

            steps = [step] * thread_count

            for i in range(0, len(steps)):
                steps[i] = steps[i] + math.ceil(remaining_lines / thread_count)
                remaining_lines -= math.ceil(remaining_lines / thread_count)
                if remaining_lines == 0:
                    break

            # Создаем список кусочков массива
            args = []
            i = 0
            for step in steps:
                args.append([i, i + step, fst, sec])
                i += step
            pool = Pool(thread_count)
            # начинаем умножение
            startTime = datetime.now()
            result = pool.starmap(work, args)
            endTime = datetime.now()
            print(f"Size of arrays: {size_arrays}")
            print(f"Count of threads: {thread_count}")
            print("Time work:", endTime - startTime)
            print("--------------")
        print("--------------------------------------------------------")