【问题标题】:Sharing a large data-structure in-memory among Python processes?在 Python 进程之间共享内存中的大型数据结构?
【发布时间】:2015-03-29 02:38:35
【问题描述】:

我们有大约 10 个 Python 进程在 Linux 机器上运行,它们都读取相同的大型数据结构(恰好是 Pandas DataFrame,本质上是一个 2D numpy 矩阵)。

这些进程必须尽快响应查询,而将数据保存在磁盘上的速度已经不足以满足我们的需求。

我们真正需要的是让所有进程能够完全随机访问内存中的数据结构,以便它们可以检索执行任意计算所需的所有元素。

由于它的大小,我们不能在内存中将数据结构复制 10 次(甚至两次)。

有没有办法让所有 10 个 Python 进程共享对内存中数据结构的随机访问?

【问题讨论】:

  • 进程是只从DataFrame中读取,还是同时读取和写入(修改DataFrame)?您使用的是什么操作系统?
  • @unutbu:它们只是在读取——数据是由不同的进程写入的,并且在写入后本质上是静态的和只读的。另外,这是 Linux (Ubuntu Server 14.04)。

标签: python performance numpy pandas architecture


【解决方案1】:

另一种解决方案有一个相当大的问题,即要求数据帧始终是静态的,并且需要Linux。

你应该看看 Redis,它虽然不如原生的 Python 内存结构快,但在同一台机器上查询表类对象的速度仍然非常快。如果您希望通过共享内存结构获得最高速度,请查看新生的Apache Arrow 项目。

两者都提供了动态数据功能和跨语言支持的巨大优势,而 Redis 还允许您使用多节点。

【讨论】:

    【解决方案2】:

    Because Linux supports Copy-on-Write (COW) on fork(),数据未复制 除非它被写入。

    因此,如果您在全局命名空间中定义 DataFrame,df,那么您 可以从任意多个随后生成的子进程访问它, 并且 DataFrame 不需要额外的内存。

    只有当其中一个子进程修改df(或与df在同一内存页上的数据)时,才会复制(在该内存页上的)数据。

    因此,尽管听起来很奇怪,但您无需在 Linux 上执行任何特殊操作即可在子进程之间共享对大型内存数据结构的访问,除了在全局命名空间中定义数据之前 em> 产生子进程。

    Here is some code 演示 Copy-on-Write 行为。


    当数据被修改时,它所在的内存页被复制。 如this PDF中所述:

    每个进程都有一个页表,将其虚拟地址映射到 物理地址;当执行 fork() 操作时,新的 进程创建了一个新的页表,其中标记了每个条目 带有“写时复制”标志;这也是为调用者的 地址空间。当内存的内容要更新时, 标志被检查。如果设置了,则分配一个新页面,数据来自 复制旧页面,在新页面上进行更新,然后 为新页面清除“写时复制”标志。

    因此,如果内存页上的某个值有更新,则该页是 复制。如果大型 DataFrame 的一部分驻留在该内存页面上,则仅复制该部分,而不是整个 DataFrame。 By default the page size is usually 4 KiB 但可能更大,具体取决于 how the MMU is configured。

    键入

    % getconf PAGE_SIZE
    4096
    

    在您的系统上查找页面大小(以字节为单位)。

    【讨论】:

    • 谢谢!有没有关于何时发生奶牛的特殊规定?例如,如果顶级__main__ 进程包含一大堆全局数据会怎样。您链接的牛解释提到了“内存页”。是否有可能其中一个分叉进程最终会触发df 的完整副本,只是因为它试图(覆盖)写入从__main__ 继承的任何更小的数据结构?
    • @DunPeal:只复制受影响的内存页面。我在上面添加了更多细节。
    • 太棒了!最后一个问题:我是否必须像您的示例中那样使用multiprocessing.Process 生成这些工作人员,以便他们可以访问__main__ 的全局范围,或者是否有另一种方法可以为他们提供这种访问权限?例如,有什么方法可以让它与不那么花哨的subprocess.Popen 一起工作?
    • 您需要使用multiprocessing 或(在Python3 中)concurrent.futures。 Here is a great tutorial 让您开始。
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 1970-01-01
    相关资源
    最近更新 更多