0

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

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

但是,每次对对象进行挖掘大约需要 1 分钟,并且我需要运行此函数最多 100 次。总而言之,在运行之前序列化对象需要将近 2 个小时。

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

非常感谢

4

1 回答 1

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使用monkeypatching 来dill代替pickle,您可以轻松地对其进行修补以使用此cachedpickle功能。


如果您使用的是 ,它是预替换的multiprocess分叉版本,那么如何修补它就不那么明显了;您需要浏览源代码并查看它在哪里使用并让它使用您的包装器。但是 IIRC,它只是做了一个地方,然后使用与(稍微过时的版本)相同的代码,所以它并没有那么不同。multiprocessingdillpickledillimport dill as picklemultiprocessing

事实上,您甚至可以编写一个模块来公开与pickle和相同的接口dill

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 pickleimport mycachingmodule as pickle.

…甚至在加载后对其进行monkeypatch (或任何适当的名称-您仍然必须在您使用的任何东西的源代码中multiprocess.helpers.pickle = mycachingmodule找到相关的发生位置)。import


这和它可能得到的一样复杂。

于 2018-06-12T21:11:47.217 回答