我正在开发一个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
我目前正在我的库中发布GIL,但是有一些未来的任务会从独立的进程中大大受益,并且我希望避免必须实现RPC系统来与BK交谈树。
答案 0 :(得分:1)
如果扩展数据将作为跨多个进程的单个逻辑可变对象存在(因此进程A中的更改将反映在进程B中的视图中),则无法避免某种IPC机制。两个进程的内存空间是分开的; Python无法神奇地共享非共享数据。
你可以获得的最接近的(没有明确使用C层的共享内存,可以用来允许将相同的内存映射到每个进程)将使用multiprocessing.BaseManager
的自定义子类,它只会隐藏来自您的IPC(实际对象将存在于单个进程中,其他进程代理该原始对象)。您可以看到a really simple example in the multiprocessing
docs。
经理方法很简单,但在性能方面,它可能不会那么热; C层的共享内存避免了代理机制无法避免的大量开销。您需要进行测试以验证任何内容。根据我的知识,使用C ++ STL使用共享内存可能是一种巨大的痛苦,可能不值得这么麻烦,所以除非管理器方法显得太慢,否则我甚至不会尝试优化。