gpt4 book ai didi

python - PyTables 处理大小比内存大很多倍的数据

转载 作者:太空狗 更新时间:2023-10-29 19:27:50 24 4
gpt4 key购买 nike

我试图了解 PyTables 如何管理大小大于内存大小的数据。这是 PyTables ( link to GitHub ) 代码中的注释:

# Nodes referenced by a variable are kept in `_aliveNodes`.
# When they are no longer referenced, they move themselves
# to `_deadNodes`, where they are kept until they are referenced again
# or they are preempted from it by other unreferenced nodes.

也可以在 _getNode 中找到有用的评论方法。
看起来 PyTables 有非常智能的 IO 缓冲系统,据我所知,它将用户引用的数据存储在快速 RAM 中作为“aliveNodes”,将之前引用的和当前未引用的数据保持为“deadNodes”以便在需要时快速“恢复”它,并且如果请求的 key 不存在于死或活类别中,则从磁盘读取数据。

我需要一些专业知识,了解 PyTables 在处理大于可用内存的数据时如何准确处理情况。我的具体问题:

  1. deadNode/aliveNode 系统如何工作(常见图片)?
  2. aliveNodes/deadNodes 之间的主要区别是什么,如果我是对的话,它们都表示存储在 RAM 中的数据?
  3. 可以手动调整用于缓冲的 RAM 限制吗?在注释下方,有代码从 params['NODE_CACHE_SLOTS'] 中读取一个值。它可以由用户以某种方式指定吗?例如,如果我想为其他也需要内存的应用程序保留一些 RAM?
  4. 在什么情况下 PyTables 在处理大量数据时会崩溃或显着变慢数据的?在我的情况下可以超出内存 100 倍,在这种情况下常见的陷阱是什么?
  5. PyTables 在大小、数据结构以及对数据的操作被认为是“正确”以获得最佳性能方面的意义是什么?
  6. Docs suggests在每个基本的 .append() 循环之后使用 .flush()。这个周期究竟能有多久?我正在执行一个小基准测试,比较 SQLite 和 PyTables 如何处理使用来自大 CSV 文件的键值对创建一个巨大的表。当我使用 .flush() 时,在主循环中使用频率较低,PyTables 获得了巨大的加速。那么 - 对 .append() 相对较大的数据 block ,然后使用 .flush() 是否正确?

最佳答案

内存结构

从未使用过 pytables,但查看源代码:

class _Deadnodes(lrucacheExtension.NodeCache):
pass

所以看起来 _deadnodes 是使用 LRU 缓存实现的。 LRU == "Least Recently Used"表示它会先丢弃最少使用的节点。来源是here .

class _AliveNodes(dict):
...

他们将其用作正在运行并在程序中实际表示的节点的自定义字典。

非常简化的示例(节点是字母,缓存中的数字表示条目的陈旧程度):

memory of 4, takes 1 time step
cache with size 2, takes 5 times steps
disk with much much more, takes 50 time steps

get node A //memory,cache miss load from disk t=50
get node B // "" t=100
get node C // "" t=150
get node D // "" t=200
get node E // "" t=250
get node A //cache hit load from cache t=255
get node F //memory, cache miss load from disk t=305
get node G //memory, cache miss load from disk t=355
get node E // in memory t=356 (everything stays the same)

t=200 t=250 t=255
Memory CACHE Memory CACHE Memory CACHE
A E A0 E B0
B B A
C C C
D D D

t=305 t=355
Memory CACHE Memory CACHE
E B1 E G0
A C0 A C1
F F
D G

如您所知,在现实生活中这些结构非常庞大,访问它们所需的时间以总线周期为单位,因此 1/(您电脑的时钟)。

比较而言,访问元素所花费的时间是相同的。它在内存中几乎可以忽略不计,在缓存中多一点,在磁盘中多得多。从磁盘读取是整个过程中最长的部分。磁盘和臂需要移动等。这是一个物理过程而不是电子过程,因为它不是以光速发生的。

在 pytables 中,他们做类似的事情。他们在 Cython 中编写了自己的缓存算法,该算法是事件节点(内存)和完整数据(磁盘)之间的中间人。如果命中率太低,那么看起来缓存将被关闭,并且在一定数量的周期后它会再次打开。

parameters.py DISABLE_EVERY_CYCLEENABLE EVERY_CYCLELOWEST_HIT_RATIO 变量用于定义在 LOWEST_HIT_RATIO 下禁用后的循环数和等待的循环数重新启用。不鼓励更改这些值。

您应该从中学到的主要内容是,如果您需要对大型数据集进行处理,请确保它们位于相同的节点上。如果你能逃脱它,读入一个 block ,在那个卡盘上做处理,得到你的结果,然后加载另一个 block 。如果加载 chunk A,获取另一个 chunk B,然后再次加载 chunk A,这将导致最大的延迟。一次只对一 block 数据进行操作,并将访问和写入保持在最低限度。一旦一个值在 _alivenodes 中,就可以快速修改它,_deadnodes 会慢一点,而且两者都不会慢很多。

NODE_CACHE_SLOTS

params['NODE_CACHE_SLOTS'] 定义死节点集的大小。追溯到parameters.py它默认为 64。它声明您可以尝试不同的值并返返回告。您可以更改文件中的值或执行以下操作:

import parameters
parameters.NODE_CACHE_SLOTS = # something else

这仅限制缓存中保留的节点数。过去你受 python 的堆大小限制,要设置它请参见 this .

附加/刷新

对于appendflush 确保行输出到表中。您移动的数据越多,数据从内部缓冲区移动到数据结构所需的时间就越长。它正在调用 H5TBwrite_records 的修改版本与其他处理代码一起使用。我猜测调用的长度决定了输出周期的长度。

请记住,这全部来自源代码,并没有考虑他们试图做的任何额外的魔法。我从未使用过 pytables。从理论上讲,它不应该崩溃,但我们并不生活在理论世界中。

编辑:

实际上我自己发现了对 pytables 的需求,我遇到了 this question在他们的常见问题解答中可能会回答您的一些疑虑。

感谢您向我展示 pytables,如果我在研究这个问题之前遇到 .h5 文件,我将不知道该怎么做。

关于python - PyTables 处理大小比内存大很多倍的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14984003/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com