为多处理序列化对象很慢 - 有没有办法只序列化一次?

时间:2018-06-12 21:04:47

标签: python python-multiprocessing pathos

我正在尝试并行化一个接受Python中对象的函数:

在使用Pathos时,map函数会在将对象分发到处理器之前自动填充对象。

然而,每次莳萝对象需要约1分钟,我需要运行此功能多达100次。总而言之,在运行它之前,只需要花费将近2个小时来序列化对象。

有没有办法只将它序列化一次,并多次使用它?

非常感谢

1 个答案:

答案 0 :(得分:2)

最简单的方法是手动执行此操作。

如果没有代码示例,我必须做出很多假设并写出一些非常含糊的内容,所以让我们采取最简单的案例。

假设您手动使用dill,因此现有代码如下所示:

obj = function_that_creates_giant_object()
for i in range(zillions):
    results.append(pool.apply(func, (dill.dumps(obj),)))

您所要做的就是将dumps移出循环:

obj = function_that_creates_giant_object()
objpickle = dill.dumps(obj)
for i in range(zillions):
    results.append(pool.apply(func, (objpickle,)))

但是根据您的实际使用情况,最好只在dill前面放一个缓存:

cachedpickle = functools.lru_cache(maxsize=10)(dill.dumps)

obj = function_that_creates_giant_object()
for i in range(zillions):
    results.append(pool.apply(wrapped_func, (cachedpickle(obj),))

当然,如果您使用multiprocessing代替dill进行monkeypatching pickle,您可以轻松修补它以使用此cachedpickle功能。

如果您正在使用multiprocess,这是multiprocessing的分叉版本,可以dill代替pickle,那么它就不那么明显了如何打补丁;您需要浏览源代码并查看它使用dill的位置并让它使用您的包装器。但是IIRC,只是在某个地方import dill as pickle,然后使用相同的代码(multiprocessing稍微过时的版本),所以它并不是那么不同。

事实上,您甚至可以编写一个公开与pickledill相同的界面的模块:

import functools
import dill

def loads(s):
    return dill.loads(s)

@lru_cache(maxsize=10)
def dumps(o):
    return dill.dumps(o)

...只需将import dill as pickle替换为import mycachingmodule as pickle

...甚至在使用multiprocess.helpers.pickle = mycachingmodule加载后进行monkeypatch(或者任何适当的名称 - 你仍然必须找到相关import在你所拥有的任何来源中发生的地方#39;重新使用)。

这就像它可能得到的那样复杂。