Python 处理数据的PyTables的大小是内存大小的许多倍
我试图理解PyTables如何管理大于内存大小的数据。 以下是PyTables()代码中的注释: 也可以在方法中找到有用的注释。Python 处理数据的PyTables的大小是内存大小的许多倍,python,io,hdf5,pytables,Python,Io,Hdf5,Pytables,我试图理解PyTables如何管理大于内存大小的数据。 以下是PyTables()代码中的注释: 也可以在方法中找到有用的注释。 PyTables似乎有非常智能的IO缓冲系统,据我所知,该系统将用户引用的数据存储在快速RAM中作为“aliveNodes”,将之前和当前未引用的数据保持为“deadNodes”,以便在需要时快速“恢复”它,并在请求的密钥不存在于死或活类别中时从磁盘读取数据 我需要一些关于PyTables在处理大于可用内存的数据时如何准确处理情况的专业知识。我的具体问题: deadN
PyTables似乎有非常智能的IO缓冲系统,据我所知,该系统将用户引用的数据存储在快速RAM中作为“aliveNodes”,将之前和当前未引用的数据保持为“deadNodes”,以便在需要时快速“恢复”它,并在请求的密钥不存在于死或活类别中时从磁盘读取数据 我需要一些关于PyTables在处理大于可用内存的数据时如何准确处理情况的专业知识。我的具体问题:
params['NODE\u CACHE\u SLOTS']
读取一个值。它可以由用户指定吗?例如,如果我想为其他也需要内存的应用程序保留一些RAM.append()
循环后使用.flush()
。这个周期实际上可以有多长?我正在执行一个小的基准测试,比较SQLite和PyTables如何处理从大型CSV文件创建具有键值对的大型表。当我在主循环中使用.flush()
的频率较低时,PyTables获得了巨大的加速。那么-使用.append()
相对较大的数据块,然后使用.flush()
,正确吗我不是PyTable1的专家,但它的工作原理很可能是
aliveNodes
位于RAM中,而deadNodes
可能以hdf5文件(PyTables使用的二进制文件格式)存储在磁盘上。
每次需要访问一段数据时,它都需要位于RAM中。所以PyTable检查它是否已经存在(aliveNodes
),如果已经存在,则返回给您。否则,它需要恢复数据所在的deadNode
。由于RAM是有限的,它可能会杀死(写入磁盘)一个未使用的aliveNode
,以便事先留出一些空间
这个过程的原因当然是RAM的大小有限。
结果是,每次需要交换节点时(杀死一个节点并恢复另一个节点),性能都会受到影响
要优化性能,应尽量减少交换。例如,如果可以并行处理数据,则可能只能加载每个节点一次。另一个例子:假设你需要循环一个巨大矩阵的每个元素,这个矩阵被分割成一个节点网格。然后,最好避免按行或列访问其元素,而是逐节点访问
当然,PyTable在幕后处理这个问题,所以您不必控制每个节点中的内容(但我鼓励您深入研究这个节点\u缓存\u插槽
变量,至少要了解它是如何工作的)。但一般来说,访问连续的数据要比访问分散的数据更快。和往常一样,如果时间性能是应用程序的一个重要问题,请分析代码
1翻译:我对PyTable几乎一无所知,我也不是PyTable方面的专家,Simon似乎已经很好地介绍了交换内存的概念,但是如果您想要一个具体的算法示例来处理太大而无法放入内存的数据,我建议您看一下外部排序 其基本思想是:不能将所有数据都放入内存中,但需要对其进行排序。但是,您可以将一些数据放入内存中,以大小为k的块为单位。假设有j个这样的块
- 将数据拆分为大小为k的块
- 对于每个块,将其放入内存并进行排序(例如使用快速排序或其他方法),然后将其排序后的版本写回磁盘
- 将每个j排序块中的最小值放入内存
- 找出这些j值中的最小值。这是最小的数据!因此,将其写入磁盘某处,作为已排序数据集的开始
- 将新写入的值替换为从其块到内存中的下一个最小值(这是交换内存的“交换”位)
class _Deadnodes(lrucacheExtension.NodeCache):
pass
因此,看起来_deadnodes是使用LRU缓存实现的。LRU==“最近使用最少的”,这意味着它将首先丢弃使用最少的节点。消息来源是
它们将其用作程序中实际运行和表示的节点的自定义字典
非常简单的示例(节点是字母,缓存中的数字表示条目的过时程度):
正如你所知,在现实生活中,这些结构是巨大的,访问它们所需的时间是以总线周期为单位的,所以1/(c)
class _Deadnodes(lrucacheExtension.NodeCache):
pass
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
import parameters
parameters.NODE_CACHE_SLOTS = # something else