Gil*_*tes 10 python io hdf5 pytables
我试图理解PyTables如何管理大小大于内存大小的数据.这是PyTables代码中的注释(链接到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.
Run Code Online (Sandbox Code Playgroud)
在_getNode方法中也可以找到有用的注释.
似乎PyTables有非常智能的IO缓冲系统,据我所知,它将用户在快速RAM中引用的数据存储为"aliveNodes",在之前保持引用,当前未引用的数据为"deadNodes",以便在需要时快速"恢复"它,以及如果请求的密钥在死或活类别中都不存在,则从磁盘读取数据.
我需要一些关于PyTables在处理大于可用内存的数据时如何处理情况的专业知识.我的具体问题:
params['NODE_CACHE_SLOTS'].它可以以某种方式由用户指定吗?例如,如果我想为其他需要内存的应用程序留下一些RAM?.flush()在每个基本.append()周期后使用.这个周期实际上可以有多长?我正在执行一些基准测试,比较SQLite和PyTables如何处理从大型CSV文件创建一个包含键值对的巨大表格.当我使用时.flush(),主循环中的频率较低,PyTables获得了巨大的加速.那么 - 对于.append()相对较大的数据块是否正确,然后使用.flush()?从未使用过 pytables,但查看了源代码:
class _Deadnodes(lrucacheExtension.NodeCache):
pass
Run Code Online (Sandbox Code Playgroud)
所以看起来 _deadnodes 是使用 LRU 缓存实现的。LRU ==“最近最少使用”这意味着它将首先丢弃最少使用的节点。来源在这里。
class _AliveNodes(dict):
...
Run Code Online (Sandbox Code Playgroud)
他们将其用作程序中实际运行和表示的节点的定制字典。
非常简单的示例(节点是字母,缓存中的数字表示条目的陈旧程度):
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
Run Code Online (Sandbox Code Playgroud)
正如您所知,在现实生活中,这些结构非常庞大,访问它们所需的时间以总线周期为单位,因此为 1/(您电脑的时钟)。
相比之下,访问元素所需的时间是相同的。对于内存来说,它可以忽略不计,对于缓存来说,要多一点,对于磁盘来说,则要多得多。从磁盘读取是整个过程中最长的部分。磁盘和臂需要移动等。这是一个物理过程而不是电子过程,因为它不是以光速发生的。
在 pytables 中,他们做了类似的事情。他们在 Cython 中编写了自己的缓存算法,它是活动节点(内存)和完整数据(磁盘)之间的中间人。如果命中率太低,那么看起来缓存将被关闭,并且在一定数量的周期后它将再次打开。
在parameters.py中DISABLE_EVERY_CYCLE, 、ENABLE EVERY_CYCLE和LOWEST_HIT_RATIO变量用于定义 LOWEST_HIT_RATIO 下禁用后的周期数以及等待重新启用的周期数。不鼓励更改这些值。
您应该从中得到的主要信息是,如果您需要对大数据集进行处理,请确保它们位于相同的节点上。如果你能逃脱它,读入一个块,在该卡盘上进行处理,得到你的结果,然后加载另一个块。如果加载块 A,获取另一个块 B,然后再次加载块 A,这将导致最大的延迟。一次仅对一大块数据进行操作,并将访问和写入保持在最低限度。一旦输入了一个值_alivenodes,修改它的速度就会很快,_deadnodes但速度会慢一点,但也不会慢很多。
params['NODE_CACHE_SLOTS']定义死节点集的大小。追溯到parameters.py,它默认为64。它表明您可以尝试不同的值并报告。您可以更改文件中的值或执行以下操作:
import parameters
parameters.NODE_CACHE_SLOTS = # something else
Run Code Online (Sandbox Code Playgroud)
这仅限制缓存中保存的节点数量。过去,你会受到 python 堆大小的限制,要设置它,请参阅this。
对于append,flush确保将行输出到表中。您移动的数据越多,数据从内部缓冲区移动到数据结构所需的时间就越长。它正在调用一个修改版本它使用其他处理代码调用H5TBwrite_records我猜测调用的长度决定了输出周期的长度。
请记住,这全部来自源代码,并没有考虑他们试图做的任何额外的魔法。我从来没有使用过 pytables。从理论上讲,它不应该崩溃,但我们并不生活在理论世界中。
编辑:
实际上我自己也发现了对 pytables 的需求,我遇到了这个问题,这可能会解答您的一些担忧。
感谢您向我展示 pytables,如果我在研究这个问题之前遇到.h5文件,我将不知道该怎么做。