如何并行化对外部程序的记忆调用?

How can I parallelize a memoized call to an external program?

我有一个用Python写的数据处理程序,需要在一个阶段调用外部程序。分析显示总处理时间的大约 50% 花在了这一阶段。

我有一台多核计算机,所以并行似乎是解决方案。问题是,电话被记忆了:

def one_stage_of_processing(long_list_of_inputs, cache={}):
    outputs = []
    for input in list_of_inputs:
        outputs.append(expensive_external_processing(input, cache))
    return outputs

def expensive_external_processing(input, cache):
    if input not in cache:
        cache[input] = subprocess.run(...).stdout
    return cache[input]

使用 C 的经验让我对竞争条件损坏缓存保持警惕。

最好、最 Pythonic 并行处理这个阶段的方法是什么?我想保留记忆,因为删除它会使运行时间增加四倍。

您可以异步启动任务,然后将 future 放入备忘录中。任何询问备忘录结果的人都会遇到三种状态之一:没有备忘录(因此启动一个新的昂贵的外部处理任务),未完成的未来备忘录(你可以等待它,或者承认它尚未完成并去做其他事情直到它完成了),或者完成了未来的备忘录(结果立即可用)。这样,您可以避免在处理完成之前发出多个相同的请求。请注意,期货仅在 3.5 后可用。

您还可以看到为什么任务需要这么长时间。如果计算很重,就没办法了;但是如果 startup 很重(这是我在做这样的事情时经常遇到的情况。在这种情况下,将其他可执行文件包装成具有循环的东西非常有用并且可以通信(最简单的是 Web 服务)。这让您拥有真正的 per-request 成本,完全避免为每个请求生成新的子进程而产生的启动成本。

您可以使用 multiprocessing to start the functions in parallel then use a multiprocessing.Queue 来保持进程之间的缓存同步。