Оптимизация значений Dict (список) Умножение - PullRequest
0 голосов
/ 04 ноября 2018

У меня есть два словарных элемента: Начальный (25 пар ключ-значение) Результаты (100 пар ключ-значение)

Initial: {0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0],....... 24: [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0]}

Results: {'0': [360, 0, 0, 0, 0, 1, 0, 0, 3, 3, 0, 0, 15, 0, 14, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 3, 3, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 2, 0, 1, 0, 0, 3, 1, 0, 1, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 137, 21, 78, 65, 241, 31, 30, 88, 152, 3, 13, 67, 31, 145, 132, 37, 1, 107, 120, 171, 39, 35, 31, 8, 24, 0, 0, 0, 0, 0],......'100': [183, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 8, 1, 3, 1, 0, 3, 3, 0, 1, 1, 3, 2, 1, 1, 4, 0, 2, 1, 3, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 76, 10, 25, 33, 121, 14, 6, 40, 62, 2, 5, 34, 23, 66, 61, 28, 1, 56, 46, 69, 23, 10, 14, 1, 13, 1, 0, 0, 0, 0]}

В каждой итерации я умножаю каждое значение словаря Результатов на одно значение в Начальном словаре и вызываю функцию, передающую продукт, который извлекает мне другое значение, и я повторяю это через весь Начальный словарь Значения. Я делаю это, используя следующий код:

for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  

Один полный цикл занимает около 1 минуты, и мне нужно выполнить не менее 5000 циклов, чтобы увидеть окончательные результаты. Любые предложения по улучшению производительности / оптимизации кода будет принята с благодарностью.

1 Ответ

0 голосов
/ 04 ноября 2018

Ваши значения являются списками, и поэтому вы должны умножать по одному элементу за раз. Вы можете сначала преобразовать свои значения (списки) в массивы, а затем использовать векторизованное умножение, что исключает использование списочного и поэлементного умножения следующим образом

# Converting the values to arrays once for all
Initial = {k:np.array(v) for k,v in Initial.items()}
Results = {k:np.array(v) for k,v in Results.items()}

# Now just using vectorized multipliction
for z in Initial.keys():
    for i in sorted(Results.keys()):
        result = {i :Initial[z] * Results[i]}  

Поскольку вы не предоставили полные данные, я попробовал ваш код около 1 миллиона итераций и обнаружил, что векторизованный код гораздо быстрее. Испытайте это на своих исходных данных и посмотрите, ускоритесь ли вы (что вам следует).


Контрольный пример для сравнения времени

Ваше понимание списка версия заняла 1 минуту 6 секунд

for ii in range(500000):
    for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  

Следующая векторизация операция заняла 2,9 секунды

for ii in range(500000):
    for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :Initial[z] * Results[i]}  
...