import numpy as np
import time
from concurrent.futures import ProcessPoolExecutor

benchmark = {}
m_a = []
m_b = []
m_c = []


# лучше не надо
def do_multiplication(size):
    global m_a
    global m_b
    global m_c

    m_a = np.random.randint(10, size=(size, size))
    m_b = np.random.randint(10, size=(size, size))
    m_c = np.zeros(shape=(size, size))
    bt = m_b.transpose()

    start_time = time.time()
    for i in range(size):
        for j in range(size):
            for k in range(size):
                m_c[i][j] = m_c[i][j] + m_a[i][k] * bt[j][k]

    return time.time() - start_time


def multiply_row(a, bt, c, size):
    for j in range(size):
        c[j] = sum(el_a * el_b for el_a, el_b in zip(a, bt[j]))
    return c


def do_multiplication_parallel(size, proc_num):
    global m_a
    global m_b
    global m_c

    if proc_num > 61:
        proc_num = 61

    m_a = np.random.randint(10, size=(size, size))
    m_b = np.random.randint(10, size=(size, size))
    m_c = np.zeros(shape=(size, size))
    bt = m_b.transpose()

    start_time = time.time()
    with ProcessPoolExecutor(max_workers=proc_num) as executor:
        results = [executor.submit(multiply_row, m_a[i], bt, m_c[i], size) for i in range(size)]
        m_c = [future.result() for future in results]

    return time.time() - start_time


def do_research():
    benchmark['size=100, proc_num=1: '] = do_multiplication_parallel(100, 1)
    benchmark['size=300, proc_num=1: '] = do_multiplication_parallel(300, 1)
    benchmark['size=500, proc_num=1: '] = do_multiplication_parallel(500, 1)
    benchmark['size=100, proc_num=10: '] = do_multiplication_parallel(100, 10)
    benchmark['size=300, proc_num=10: '] = do_multiplication_parallel(300, 10)
    benchmark['size=500, proc_num=10: '] = do_multiplication_parallel(500, 10)
    benchmark['size=100, proc_num=100: '] = do_multiplication_parallel(100, 100)
    benchmark['size=300, proc_num=100: '] = do_multiplication_parallel(300, 100)
    benchmark['size=500, proc_num=100: '] = do_multiplication_parallel(500, 100)
    print(benchmark)


if __name__ == '__main__':
    do_research()


def get_results(size, proc_num):
    global m_a
    global m_b
    global m_c

    res = "time: "
    res = res + str(do_multiplication_parallel(size, proc_num))

    res = res + "<br/>"
    for i in range(size):
        res = res + "<p>"
        for a in range(size):
            res = res + str(m_a[i][a]) + ", "
        res = res + "&emsp;"
        for b in range(size):
            res = res + str(m_b[i][b]) + ", "
        res = res + "&emsp;"
        for c in range(size):
            res = res + str(m_c[i][c]) + ", "
        res = res + "</p>"

    return res


def get_benchmark():
    global benchmark

    if len(benchmark) == 0:
        do_research()

    res = ''
    for key, val in benchmark.items():
        res = res + "<p>" + key + str(val) + "</p>"

    return res