【问题标题】:Implementing Python integer key and value numpy dictionary实现 Python 整数键和值 numpy 字典
【发布时间】:2014-10-28 22:29:40
【问题描述】:

我有大量数据需要快速查找,通常我会使用字典。但是,我需要存储大约 6 亿个键值对,而当尝试将其存储在字典中时,它不适合内存。

我意识到如果字典将键和值存储为具有固定长度(即 32 位)的整数,则它可以节省内存。我可以通过使用 numpy 数组来解决我的问题,对数据进行排序,然后使用搜索来找到正确的值(占用大约 8GB):

import numpy as np    
key_a = np.zeros(600e6, dtype=np.int64)
values_a = np.zeros(600e6, dtype=np.int32)

# ... Fill arrays ...

# Find value using key:
index = np.searchsorted(key_a, key_to_find)    
value_to_find = values_a[index]

这种方法不如使用哈希快。

我最理想的做法是实现一个字典,但使用固定大小的 numpy 数组作为主干以节省空间?我还希望字典针对整数进行优化。为什么 numpy 还没有提供这样的东西,我将如何去做呢?

【问题讨论】:

  • 据我所知,numpy 数组并不打算用作数据库,即快速索引。也许 pandas (pandas.pydata.org) 可以帮助你...
  • 您是否考虑过使用像dbm 这样的磁盘结构?它显然不会像自定义 int32 哈希那样快速或紧凑,但它会简单得多(例如,只需一个 import 语句,而不是您必须编写和调试的 100 行代码),而且它还免费为您提供持久性(我猜您会想要)。
  • 速度至关重要,因此内存解决方案更可取
  • 我应该早点问这个,但是……你经常查找一堆彼此靠近的键吗?如果是这样,哈希将比排序数组产生严重成本,因为您将丢失所有缓存和 VM 局部性。而且,根据您的数据分布情况,有一些方法可以加快二进制搜索的速度,这可能会有所帮助。
  • @abarnert 是的,密钥只在一定范围内。如何加快二分搜索?

标签: python numpy dictionary


【解决方案1】:

我最理想的做法是实现一个字典,但使用固定大小的 numpy 数组作为主干以节省空间

一个固定大小的数组显然会给你一个固定大小的字典。 (您显然不能进行链接,因为您不能将链表粘贴到一个 numpy 整数数组中……)这可以接受吗?

我还希望字典针对整数进行优化。

这究竟意味着什么?您仍然需要对整数进行哈希处理才能获得适当的键分布。也许你可以为固定大小的整数想出一个稍微快一点的散列函数,但我怀疑它会给你带来很多性能优势。

为什么 numpy 还没有提供类似的东西

因为它与 numpy 的全部内容(数值编程)的关系并不密切。事实上,即使是 与 numpy 有点相关但不够“基本”的东西也往往会被分流到像 scipy 这样的库中,而不是在 numpy 本身中。

我该怎么做呢?

你不知道如何实现哈希表吗? StackOverflow 的答案不是学习基本数据结构基础知识的地方,但 Wikipedia's article 的答案看起来不错。

如果您希望它尽可能地像 Python 的 dict 的哈希表一样工作,最好的办法是查看源代码。 CPython 实际上很好地解释了它在 cmets 中的工作原理。但当然它是 C 代码,而不是 Python,所以除非你了解一些基本的 C 并了解它在做什么,否则它对你来说毫无意义。你可能想看看 PyPy——虽然它的源代码有点复杂(它有许多 CPython 没有的优化),但它是在 Python 中的。

还有很多custom hash table implementations on PyPI

您也可以查看fixedhash。我把它写成一个尽可能简单的哈希表作为基础来展示不同探测函数的影响(它开始是简单的线性探测),但我想它也应该作为展示如何构建尽可能简单的哈希表。 :) 它是围绕 bytearray 构建的,用于存储 8 字节 bytes 键和值;将其更改为使用 np.ndarray 来存储 4 字节整数键和值应该是显而易见的,并且您可以使用 Nx3 或 Nx4 数组这一事实应该使其更具可读性(struct.pack 的东西都没有)。

【讨论】:

  • 这个答案给了我很多方向,谢谢。
猜你喜欢
  • 2014-07-03
  • 2020-10-23
  • 1970-01-01
  • 2019-02-05
  • 2021-08-02
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多