在没有额外内存成本的情况下在进程之间共享 NetworkX 图(只读)

Sharing NetworkX graph between processes with no additional memory cost (read-only)

我正在使用 python 的多处理模块。我有一个 networkx 图,我希望在许多子进程之间共享它。这些子进程不会以任何方式修改图形,只会读取其属性(节点、边等)。现在每个子进程都有自己的图表副本,但我正在寻找一种在所有子进程之间共享图表的方法,这将减少整个程序的内存占用。由于计算非常 CPU 密集,我希望以不会导致大性能问题的方式完成此操作(尽可能避免锁定等)。

注意:我希望它能在各种操作系统上运行,包括 Windows,这意味着 COW 没有帮助(如果我理解正确,它可能无论如何都不会帮助,因为引用计数) )

我发现 https://docs.python.org/3/library/multiprocessing.html#proxy-objects 并且 https://docs.python.org/3/library/multiprocessing.shared_memory.html,但我不确定哪个(或者是否有任何一个)合适。解决这个问题的正确方法是什么?我正在使用 python 3.8,但如果有帮助,可以使用更高版本。

在多处理过程中 python 中有一些共享数据的选项,但您可能无法完全按照自己的意愿进行操作。

在 C++ 中,您可以为整数、浮点数、结构等使用简单的共享内存。Python 的共享内存管理器允许这种类型的简单对象共享,但它不适用于类 或任何比基本类型列表更复杂的东西。对于共享的复杂 python 对象,您实际上只有几个选择...

  1. 在您的分叉进程中创建对象的副本(听起来您不想这样做)。

  2. 将对象置于集中式进程中(即.. python 的管理器/代理对象)并通过管道和腌制数据与其交互。

  3. 将您的 networkX 图转换为简单整数列表并将其放入共享内存中。

什么对你有用取决于一些细节。选项 #2 有一点开销,因为每次您需要访问对象时,数据都必须被 pickle 并通过管道传输到集中式进程,结果 pickled/piped for return。如果您一次只需要一小部分集中数据并且您的处理步骤相对较长(与 pickle/pipe 时间相比),则此方法很有效。

选项 #3 可能需要大量工作。您将从根本上将数据格式从 networkX 对象更改为整数列表,因此它将改变您进行大量处理的方式。

前一段时间我把 PythonDataServe 放在一起,它允许您将数据从另一个进程发送到多个进程。这是与上面#2 非常相似的解决方案。如果您一次只需要一小部分数据,但如果您需要所有数据,则这种方法很有效,只创建一个本地副本要容易得多。