我们在Linux机器上运行大约10个Python进程,所有这些进程都读取相同的大型数据结构(恰好是Pandas DataFrame
,本质上是2D numpy矩阵)。
这些进程必须尽快响应查询,并且将数据保存在磁盘上的速度根本不足以满足我们的需求。
我们真正需要的是让所有进程能够完全随机访问内存中的数据结构,这样他们就可以检索执行任意计算所需的所有元素。
由于数据结构的大小,我们无法在内存中复制数据结构10次(甚至两次)。
有没有办法让所有10个Python进程可以共享对内存中数据结构的随机访问?
答案 0 :(得分:7)
fork()
上的Because Linux supports Copy-on-Write(COW),不会复制数据 除非写入。
因此,如果您在全局命名空间中定义DataFrame,df
,那么您
可以访问来自任意多个随后生成的子流程,如您所愿
并且不需要额外的DataFrame内存。
仅当其中一个子进程修改df
(或与df
在同一内存页面上的数据)时,才会复制数据(在该内存页面上)。
所以,听起来很奇怪,你不需要在Linux上做任何特殊的事情来共享对子进程之间的大型内存数据结构的访问,除了在>之前定义全局命名空间中的数据em>产生子进程。
Here is some code演示了写时复制行为。
修改数据后,会复制其所在的内存页面。 如this PDF:
中所述每个进程都有一个页面表,用于将其虚拟地址映射到 物理地址;当fork()操作执行时,新的 process创建了一个新的页表,其中标记了每个条目 带有''copy-on-write''标志;这也是为来电者做的 地址空间。当要更新内存的内容时, 标志被检查。如果已设置,则分配新页面,数据来自 复制旧页面,更新在新页面上进行,并且 为新页面清除''copy-on-write''标志。
因此,如果内存页面上的某个值有更新,那么该页面就是 复制。如果大型DataFrame的一部分驻留在该内存页面上,则只复制该部分,而不是整个DataFrame。 By default the page size is usually 4 KiB但可以更大,具体取决于how the MMU is configured。
输入
% getconf PAGE_SIZE
4096
查找系统上的页面大小(以字节为单位)。
答案 1 :(得分:0)
另一个解决方案存在相当大的问题,即要求数据帧始终是静态的,并且需要Linux。
你应该看看Redis,它虽然没有原生python内存结构那么快,但在同一台机器上查询类似对象的速度仍然超级快。如果您希望通过共享内存结构获得最高速度,请查看新生的Apache Arrow项目。
两者都提供了动态数据功能和跨语言支持的巨大优势,而Redis也允许您使用多节点。