Есть ли что-то быстрее, чем dict()?
Я ищу более быстрый способ хранения и доступа к примерно 3 ГБ пар k:v
, где k
— это строка или целое число, а v
— это np.array()
с различными формами.
Существует ли какой-либо объект, который быстрее стандартного словаря Python для хранения и доступа к такой структуре данных? Например, может ли pandas.DataFrame
быть более эффективным вариантом?
Насколько я понимаю, стандартный словарь Python — это довольно быстрая реализация хеш-таблицы. Есть ли что-то лучшее для моего конкретного случая?
4 ответ(ов)
Нет, я не думаю, что есть что-то быстрее, чем dict
. Средняя временная сложность проверки индекса составляет O(1)
.
-------------------------------------------------------
Операция | Средний случай | Амортизированный худший случай |
-------------------------------------------------------
Копирование[2]| O(n) | O(n) |
Получение | O(1) | O(n) |
Установка[1] | O(1) | O(n) |
Удаление | O(1) | O(n) |
Итерация[2] | O(n) | O(n) |
-------------------------------------------------------
P.S. Для получения дополнительной информации, вы можете ознакомиться с вики Python о временной сложности.
Вы можете заметить, что при сравнении времени выполнения операций над numpy.array
и классическим словарем (dict
), результаты показывают, что доступ к элементам массива происходит медленнее, чем к элементам словаря.
В вашем коде вы сначала создаете двухмерный массив размером 400x400 с помощью numpy.ones()
, а затем суммируете значения в этом массиве. После этого вы создаете словарь, в который добавляете такие же пары ключ-значение, и выполняете аналогичную операцию суммирования для словаря.
По результатам тестирования, время для расчетов с массивом выглядит так:
Time for array calculations: 0.07558204099999999
А для словаря:
Time for dict calculations: 0.046898419999999996
Поскольку доступ к элементам в словаре осуществляется через хеширование, это обеспечивает быструю выборку значений по ключу. Тем не менее, numpy
предоставляет оптимизированные функции для обработки массивов, и хотя прямые обращения к элементам могут быть медленнее, производительность numpy
может значительно возрасти для более сложных операций, поскольку он использует векторизацию и другие оптимизации.
Таким образом, для простых случаев на малых объемах данных словарь может оказаться быстрее, но при более серьезных вычислениях и больших данных numpy
обычно превосходит по производительности благодаря своей внутренней реализации.
Одним может показаться, что индексирование массива быстрее, чем поиск в хэш-таблице. Если бы мы могли хранить данные в массиве NumPy и предположить, что ключи — это не строки, а числа, было бы это быстрее, чем использование словаря в Python?
К сожалению, нет, потому что NumPy оптимизирован для векторных операций, а не для индивидуального поиска значений. Даже Pandas показывает еще худшие результаты. Вы можете ознакомиться с экспериментом здесь: Проверка производительности.
Другим вариантом может быть использование массива из модуля array в Python, но он не подходит для переменных значений. Чтобы это работало, вам, скорее всего, потребуется обернуть его в код на чистом Python, что сведет на нет все преимущества по производительности, которые предлагает массив.
Таким образом, даже если требования оригинального вопроса немного смягчить, по-прежнему не кажется, что есть более быстрый вариант, чем словари.
Вы можете рассмотреть возможность хранения данных в структуре данных, такой как Trie, если ваш ключ - это строка. Для хранения и извлечения данных из Trie вам потребуется O(N), где N - это максимальная длина ключа. То же самое происходит и с вычислением хеш-функции, которая вычисляет хеш для ключа. Хеш используется для поиска и хранения в хеш-таблице. Часто мы не учитываем время или вычисления, связанные с хешированием.
Попробуйте использовать Trie, который должен демонстрировать примерно ту же производительность, возможно, даже немного быстрее (если значение хеша вычисляется, скажем, по формуле
HASH[i] = (HASH[i-1] + key[i-1]*256^i % BUCKET_SIZE) % BUCKET_SIZE
или что-то подобное из-за коллизий, где нам необходимо использовать 256^i).
Вы можете попробовать хранить данные в Trie и посмотреть, как это будет работать.
Как вернуть ключи словаря в виде списка в Python?
Ошибка: "'dict' объект не имеет метода 'iteritems'"
Преобразование байтового массива обратно в массив numpy
Фиксация количества знаков после запятой с помощью f-строк
Как извлечь частоту, связанную с FFT значениями в Python?