我正在尝试并行化一个接受Python中对象的函数:
在使用Pathos时,map函数会在将对象分发到处理器之前自动填充对象。
然而,每次莳萝对象需要约1分钟,我需要运行此功能多达100次。总而言之,在运行它之前,只需要花费将近2个小时来序列化对象。
有没有办法只将它序列化一次,并多次使用它?
非常感谢
答案 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
稍微过时的版本),所以它并不是那么不同。
事实上,您甚至可以编写一个公开与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 pickle
替换为import mycachingmodule as pickle
。
...甚至在使用multiprocess.helpers.pickle = mycachingmodule
加载后进行monkeypatch(或者任何适当的名称 - 你仍然必须找到相关import
在你所拥有的任何来源中发生的地方#39;重新使用)。
这就像它可能得到的那样复杂。