【发布时间】:2021-05-19 08:36:32
【问题描述】:
我有一个函数可以为任务列表创建一些结果。我想将结果即时保存到 1) 释放内存,而不是保存到附加到 results_list 和 2) 有第一部分的结果以防出错。
这是一个非常短的示例代码:
for task in task_list:
result = do_awesome_stuff_to_task(task)
save_nice_results_to_db(result) # Send this job to another process and let the main process continue
主进程有没有办法为 task_list 中的每个任务创建结果,并且每次创建结果时都将其发送到另一个处理器/线程以保存它,因此主循环可以继续而无需等待缓慢的保存过程?
我看过多处理,但这似乎主要是为了加快 task_list 上的循环,而不是允许辅助子进程完成其他部分的工作。我也研究过 asyncio,但这似乎主要用于 I/O。
总而言之,我正在寻找一种方法让主进程在 task_list 上循环。对于完成的每个任务,我想将结果发送到另一个子流程以保存结果。请注意,do_awesome_stuff_to_task 比保存过程快得多,因此,在保存第一个任务之前,主循环将通过多个任务。我想了两种方法来解决这个问题:
- 使用多个子进程保存
- 保存每 xx 次迭代 - save_results 规模正常,所以也许保存过程可以在主循环继续时一次保存 xx 次迭代?
这可能与Python有关吗?在哪里查看以及需要考虑哪些关键因素?
感谢所有帮助。
【问题讨论】:
-
如果
save_results因磁盘速度而变慢,多处理可能会使情况变得更糟 -
我可能会因为多种原因变慢。无论如何,我想知道,Python 是否可以实现类似请求的操作
-
一般来说,在进程之间传递数据不是很快也不是很有效。您可以通过使用类似
multiprocessing.shared_memory的方式更快地传输信息来减少开销,但这并不简单。如果可以让save_results释放 GIL,线程是你最好的选择。同样,如果您依赖于 spin rust,进行更多并发调用将导致整体吞吐量变慢 -
也许我应该澄清一下;我建议在任何时候需要在并发发生的事情之间传输大量数据时对多处理进行线程化,因为线程共享内存空间并且没有这样的“传输”。您需要保护对象免受并发访问,以免损坏数据,但不会产生传输开销。然而,GIL 限制了您可以从线程中获得的额外 CPU 收益,但是如果您使用释放 GIL 的东西,您可以解决这个问题(包括许多 IO 操作、numpy 等......)
-
@Aaron 如果您将评论写为答案,我会将其标记为答案 - 也许您会给出一个使用线程以及如何释放 GIL 的简单示例?
标签: python-3.x multiprocessing subprocess python-asyncio