在Python进程中共享内存中的大型数据结构?

Dun*_*eal 4 python architecture performance numpy pandas

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

这些进程必须尽快响应查询,并且将数据保存在磁盘上的速度根本不足以满足我们的需求.

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

由于其大小,我们无法在内存中复制数据结构10次(甚至两次).

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

unu*_*tbu 7

由于Linux支持写入时复制(COW)fork(),因此除非写入数据,否则不会复制数据.

因此,如果df在全局命名空间中定义DataFrame,则可以根据需要从随后生成的子进程中访问它,并且不需要额外的DataFrame内存.

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

因此,听起来很奇怪,除了在生成子进程之前定义全局命名空间中的数据之外,您不必在Linux上执行任何特殊操作来共享对子进程之间的大型内存中数据结构的访问.

以下是一些演示Copy-on-Write行为的代码.


修改数据后,将复制其所在的内存页面.如本PDF所述:

每个进程都有一个页表,它将其虚拟地址映射到物理地址; 当执行fork()操作时,新进程创建了一个新的页表,其中每个条目都标有"'copy-on-write''标志; 这也是调用者的地址空间.当要更新存储器的内容时​​,检查该标志.如果已设置,则分配新页面,复制旧页面中的数据,在新页面上进行更新,并为新页面清除"写时复制"标志.

因此,如果对内存页面上的某些值进行更新,则会复制该页面.如果大型DataFrame的一部分驻留在该内存页面上,则只复制该部分,而不是整个DataFrame. 默认情况下,页面大小通常为4 KiB,但可能会更大,具体取决于MMU的配置方式.

类型

% getconf PAGE_SIZE
4096
Run Code Online (Sandbox Code Playgroud)

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