在python进程中共享扩展分配的数据结构

时间:2015-12-01 04:28:31

标签: python c++ python-3.4 python-multiprocessing

我正在开发一个python扩展,它在大型(5GB +)内存数据结构中执行一些特殊的树事务。

底层数据结构已经是线程安全的(它使用RW锁),并且我已经在它周围编写了一个包装器,将它暴露给python。它支持多个同时读取器,只有一个写入器,并且我使用pthread_rwlock进行访问同步。由于应用程序非常重读,因此多个读者应该提供适当的性能改进(我希望)。

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

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

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

源是here(仅限C ++ Header库)和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交谈树。

1 个答案:

答案 0 :(得分:1)

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

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

经理方法很简单,但在性能方面,它可能不会那么热; C层的共享内存避免了代理机制无法避免的大量开销。您需要进行测试以验证任何内容。根据我的知识,使用C ++ STL使用共享内存可能是一种巨大的痛苦,可能不值得这么麻烦,所以除非管理器方法显得太慢,否则我甚至不会尝试优化。