跨 python 个进程共享扩展分配的数据结构

Sharing extension-allocated data structures across python processes

我正在开发 python 扩展,它在大型 (5GB+) 内存数据结构上执行一些专门的树操作。

底层数据结构已经是线程安全的(它使用 RW 锁),我已经围绕它编写了一个包装器,将它暴露给 python。它支持多个同时读取器,只有一个写入器,我正在使用 pthread_rwlock 进行访问同步。由于应用程序的读取量很大,多个读取器应该会提供不错的性能改进(我希望)。

但是,我无法确定允许扩展数据存储在通过 multiprocessing 模块访问的多个 python 进程之间共享的正确解决方案。

基本上,我想要看起来像当前 multiprocessing.Value/multiprocessing.Array 系统的东西,但这里需要注意的是,我的扩展在 C++ 中分配了它自己的所有内存。

如何允许多个进程访问我的共享数据结构?

来源是 here (C++ Header-only library), and here(Cython 包装器)。

现在,如果我构建树的一个实例,然后将引用传递给多个进程,它会失败并出现序列化错误:

Traceback (most recent call last):
  File "/usr/lib/python3.4/multiprocessing/queues.py", line 242, in _feed
    obj = ForkingPickler.dumps(obj)
  File "/usr/lib/python3.4/multiprocessing/reduction.py", line 50, in dumps
    cls(buf, protocol).dump(obj)
TypeError: cannot serialize '_io.TextIOWrapper' object

(failing test-case)

我目前正在我的库中发布 GIL,但是未来的一些任务会从独立进程中受益匪浅,我想避免必须实施 RPC 系统来与 BK 树对话。

如果扩展数据将作为单个逻辑可变对象存在于多个进程中(因此进程 A 中的更改将反映在进程 B 中的视图中),您无法避免某种 IPC 机制.两个进程的内存空间是分开的; Python 无法神奇地共享未共享的数据。

你能得到的最接近的(没有在 C 层显式使用可用于允许将相同内存映射到每个进程的共享内存)是使用 multiprocessing.BaseManager 的自定义子类,这将只需向您隐藏 IPC(实际对象将存在于单个进程中,其他进程代理该原始对象)。可以看到a really simple example in the multiprocessing docs.

管理器方法很简单,但在性能方面它可能不会那么火爆; C层的共享内存避免了很多代理机制无法避免的开销。你需要测试来验证任何事情。据我所知,让 C++ STL 使用共享内存是一件非常痛苦的事情,可能不值得这么麻烦,所以除非管理器方法被证明太慢,否则我什至会避免尝试优化。