Оптимизация парсинга массивного python словаря, многопоточность - PullRequest
1 голос
/ 09 марта 2020

Давайте рассмотрим небольшой пример python словарь, где значения являются списками целых чисел.

example_dict1 = {'key1':[367, 30, 847, 482, 887, 654, 347, 504, 413, 821],
    'key2':[754, 915, 622, 149, 279, 192, 312, 203, 742, 846], 
    'key3':[586, 521, 470, 476, 693, 426, 746, 733, 528, 565]}

Допустим, мне нужно проанализировать значения списков, которые я реализовал в следующую функцию:

def manipulate_values(input_list):
    return_values = []
    for i in input_list:
        new_value = i ** 2 - 13
        return_values.append(new_value)
    return return_values

Теперь я могу легко проанализировать значения этого словарь выглядит следующим образом:

for key, value in example_dict1.items():
    example_dict1[key] = manipulate_values(value)

, что приводит к следующему:

example_dict1 = {'key1': [134676, 887, 717396, 232311, 786756, 427703, 120396, 254003, 170556, 674028], 
     'key2': [568503, 837212, 386871, 22188, 77828, 36851, 97331, 41196, 550551, 715703], 
     'key3': [343383, 271428, 220887, 226563, 480236, 181463, 556503, 537276, 278771, 319212]}

Это очень хорошо работает для небольших словарей.

Моя проблема в том, что у меня огромный словарь с миллионами ключей и длинными списками. Если бы я применил вышеуказанный подход, алгоритм был бы непомерно медленным.

Как я могу оптимизировать вышеперечисленное?

(1) Многопоточность --- существуют ли более эффективные опции для многопоточности этого оператора в словаре, кроме традиционного модуля threading?

(2) Подойдет ли лучшая структура данных?

Я задаю этот вопрос, поскольку я совершенно не понимаю, как лучше поступить в этом случае. Я не вижу лучшей структуры данных, чем словарь, но циклы for в словаре (а затем и в списках значений) довольно медленные. Здесь может быть что-то, что было разработано, чтобы быть быстрее.

РЕДАКТИРОВАТЬ: Как вы можете себе представить, это своего рода игрушечный пример - рассматриваемая функция немного сложнее, чем х ** 2-13.

Меня больше интересует, как, возможно, использовать словарь с миллионами ключей и длинными списками значений.

Ответы [ 2 ]

4 голосов
/ 09 марта 2020

Если вы можете хранить все внутри массива numpy, обработка будет быстрее. Я увеличил размер каждого списка в 0,5 миллиона раз для проверки масштабируемости. Вот мои результаты:

from timeit import timeit
import numpy as np

n = 500000
example_dict1 = {'key1':[367, 30, 847, 482, 887, 654, 347, 504, 413, 821]*n,
    'key2':[754, 915, 622, 149, 279, 192, 312, 203, 742, 846]*n, 
    'key3':[586, 521, 470, 476, 693, 426, 746, 733, 528, 565]*n}

def manipulate_values(input_list):
    return_values = []
    for i in input_list:
        new_value = i ** 2 - 13
        return_values.append(new_value)
    return return_values

С вашим методом:

for_with_dictionary = timeit("""
for key, value in example_dict1.items():
    example_dict1[key] = manipulate_values(value)
""", "from __main__ import example_dict1,manipulate_values ",number=5)

print(for_with_dictionary)

>>> 33.2095841

С numpy:

numpy_broadcasting = timeit("""
array = np.array(list(example_dict1.values()))
array = array ** 2 - 13
""", "from __main__ import example_dict1, np",number=5)
print(numpy_broadcasting)

>>> 5.039885

Значительное повышение скорости, по крайней мере, в 6 раз.

1 голос
/ 09 марта 2020

Если у вас достаточно оперативной памяти:

example_dict2 = dict(zip(example_dict1.keys(), np.array(list(example_dict1.values()))**2 -13))
>>> example_dict2
{'key1': array([134676,    887, 717396, 232311, 786756, 427703, 120396, 254003,
       170556, 674028]), 'key2': array([568503, 837212, 386871,  22188,  77828,  36851,  97331,  41196,
       550551, 715703]), 'key3': array([343383, 271428, 220887, 226563, 480236, 181463, 556503, 537276,
       278771, 319212])}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...