我正在使用a LRU cache来加速一些相当繁重的处理。它运作良好,可以大大加快速度。然而...
当我进行多处理时,每个进程都会创建自己独立的缓存,并且有8个相同的副本。这似乎不是一个问题,直到盒子耗尽内存并且结果发生了不好的事情......
理想情况下,我只需要一个大约300个项目的缓存大小,1 * 300将适合我必须使用的7GB,但8 * 300只适合。
如何让所有进程共享同一个缓存?
答案 0 :(得分:8)
我相信你可以使用Manager
在进程之间共享一个dict。从理论上讲,这应该允许您为所有函数使用相同的缓存。
但是,我认为更合理的逻辑是让一个进程通过在缓存中查找它们来响应查询,如果它们不存在则将工作委托给子进程,并且在返回之前缓存结果。你可以轻松地用
做到这一点with concurrent.futures.ProcessPoolExecutor() as e:
@functools.lru_cache
def work(*args, **kwargs):
return e.submit(slow_work, *args, **kwargs)
请注意,work
将返回Future
个对象,消费者必须等待这些对象。 lru_cache
将缓存未来的对象,以便自动返回;我相信您可以多次访问他们的数据,但现在无法测试。
如果您不使用Python 3,则必须安装concurrent.futures
和functools.lru_cache
的反向移植版本。
答案 1 :(得分:0)
将共享缓存传递给每个进程。父进程可以实例化单个缓存并将其作为参数引用到每个进程...
@utils.lru_cache(maxsize=300)
def get_stuff(key):
return Stuff(key)
def process(stuff_obj):
# get_stuff(key) <-- remove it from here
stuff_obj.execute()
def iterate_stuff(keys):
for key in keys:
yield get_stuff(key) # <-- and put it here
def main():
...
keys = get_list_of_keys()
for result in pool.imap(process, iterate_stuff(keys)):
evaluate(result)
...
Katriel让我走上正轨,我会实现这个答案,但是,愚蠢的我,这实际上比[适用于此应用程序]更容易。