多个进程共享一个Joblib缓存

11
我在我的Python脚本中使用Joblib来缓存计算密集型函数的结果。该函数的输入参数和返回值是numpy数组。缓存对于单次运行我的Python脚本有效。现在,我想并行运行多个Python脚本以扫描实验中的某些参数。(函数的定义在所有运行中保持不变)。 是否有一种方法可以在并行运行的多个Python脚本之间共享Joblib缓存?这将节省许多在不同运行中重复但在单个运行中不重复的函数评估。我无法确定这是否在Joblib文档中可能。

1
如果您已经在脚本的单个运行中进行了并行化,我认为尝试跨多个运行并行化不会有太大的收益。我想您可以通过重复使用先前运行的缓存来实现更好的效果。我从未尝试过这样做,但我猜测您可以通过在连续运行中使用相同的joblib.Memory对象来实现。 - ali_m
@ali_m:单次运行已经并行化了,但我也需要同时运行多个实例,因为每个实例需要数天时间,而且我有很多核心可用(我正在集群上运行这些)。如果joblib的缓存是一个文件,那么似乎多个进程可以共享它...但我不知道该怎么做。 - Neha Karanjkar
1
如果你在 mem.cache 重复的功能,那么这应该可以直接使用。至少在一个具有多进程的机器上是可以的。但是在多个不共享磁盘空间的集群上是完全不同的事情。如果它们共享磁盘空间并且你把缓存放在那里,我不认为它不会工作。 - eickenberg
1
@eickenberg...谢谢! :) 我想我之前使用了cachedir = mkdtemp(),这就是为什么它之前无法工作的原因。只要两个进程都使用相同的目录来保存缓存,它就可以工作。 - Neha Karanjkar
很高兴能帮上忙,这对于那些从缓存中加载所需时间明显少于计算时间的重复函数非常有用。 - eickenberg
显示剩余2条评论
1个回答

14

指定一个共同的、固定的cachedir,并使用装饰器修饰您想要缓存的函数。

from joblib import Memory
mem = Memory(cachedir=cachedir)

@mem.cache
def f(arguments):
    """do things"""
    pass

或者简单地说

def g(arguments):
   pass

cached_g = mem.cache(g)

那么,即使您在跨进程、跨机器工作,如果程序的所有实例都可以访问cachedir,那么通用函数调用就可以在那里被透明地缓存。


5
实际上,我们(joblib开发团队)小心设计基于磁盘的存储方式,使其能够经受住并行访问(尤其是并行写入)的考验。顺便提一下,我倾向于以上回答中第二种语法而不是第一种。 - Gael Varoquaux
@GaelVaroquaux,请您详细说明为什么您更喜欢后者?我的Tornado Web应用程序中到处都有@mem.cache,我想知道是否有理由将它们重构为推荐的替代方法。谢谢! - Kevin Ghaboosi
@GaelVaroquaux 另外,我想知道是否值得为异步访问装饰一个函数,就像使用@gen.coroutine一样,如果获取任务比通常需要更长时间,并且该函数是从HTTP端点或延迟敏感的客户端调用的话,谢谢! - Kevin Ghaboosi
1
我认为@符号只是第二种方法的简写版本。因此,第二种方法明确了装饰的含义,并且使您有可能不会失去原始的非装饰函数。在交互式会话中,由于名称更改,只有第二个选项适用的情况可能会出现。 - eickenberg
2
@GaelVaroquaux 很久之后才回复.... 当你说“主要是并行写入”,“主要”是什么意思?有什么重要的坑点吗?它们被记录在哪里了?谢谢。 - Caleb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接