Python 处理数据的PyTables的大小是内存大小的许多倍

Python 处理数据的PyTables的大小是内存大小的许多倍,python,io,hdf5,pytables,Python,Io,Hdf5,Pytables,我试图理解PyTables如何管理大于内存大小的数据。 以下是PyTables()代码中的注释: 也可以在方法中找到有用的注释。 PyTables似乎有非常智能的IO缓冲系统,据我所知,该系统将用户引用的数据存储在快速RAM中作为“aliveNodes”,将之前和当前未引用的数据保持为“deadNodes”,以便在需要时快速“恢复”它,并在请求的密钥不存在于死或活类别中时从磁盘读取数据 我需要一些关于PyTables在处理大于可用内存的数据时如何准确处理情况的专业知识。我的具体问题: deadN

我试图理解PyTables如何管理大于内存大小的数据。 以下是PyTables()代码中的注释:

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

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

  • deadNode/aliveNode系统如何工作(常见图片)
  • 如果im是正确的,那么aliveNodes/deadNodes代表存储在RAM中的数据时,它们之间的关键区别是什么
  • 可以手动调整缓冲RAM的限制吗?在注释下面,有一段代码从
    params['NODE\u CACHE\u SLOTS']
    读取一个值。它可以由用户指定吗?例如,如果我想为其他也需要内存的应用程序保留一些RAM
  • 在什么情况下,PyTables在处理大量数据时会崩溃或显著减速 数据量?在我的例子中,记忆可以超过100倍,在这种情况下,常见的陷阱是什么
  • PyTables在数据的大小、结构以及对被认为是“正确”的数据进行操作以获得最佳性能方面有什么用途
  • 在每个基本
    .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排序块中的最小值放入内存
    • 找出这些j值中的最小值。这是最小的数据!因此,将其写入磁盘某处,作为已排序数据集的开始
    • 将新写入的值替换为从其块到内存中的下一个最小值(这是交换内存的“交换”位)
    现在,内存中的数据是最小的j,除了我们已经写入磁盘上最终排序数据集中的数据。所以,如果我们重复这个过程,直到所有数据都被写入最终的集合,它将总是被排序

    所以,这只是一个使用内存交换来处理太大而无法放入内存的数据的算法示例。PyTable的排序方法可能是这样的

    奖励:链接是外部排序的更多解释。

    内存结构 从未使用pytables,但查看源代码:

    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