我试图用multiprocessing.Pool
分析一个大货架。使用只读模式它应该是线程安全的,但它接着首先读取一个大对象,然后通过池调度slowwwwly。这可以更有效地完成吗?
这是我正在做的最小例子。假设test_file.shelf
已经存在并且很大(14GB +)。我可以看到这个剪辑拥抱20GB的RAM,但只有一小部分的搁架可以同时读取(比处理器更多的项目)。
from multiprocessing import Pool
import shelve
def func(key_val):
print(key_val)
with shelve.open('test_file.shelf', flag='r') as shelf,\
Pool(4) as pool:
list(pool.imap_unordered(func, iter(shelf.items()))
货架本身不能快速打开,因为它们像对象一样工作,当你打开它们时,由于它在后端工作的方式,加载需要一些时间,特别是对于大型货架。为了使其像对象一样起作用,每次获得一个新项目时,该项目都会被加载到内存中的单独字典中。 lib reference
也来自docs:
(imap)对于非常长的迭代,使用较大的chunksize值可以使作业完成比使用默认值1更快。
您使用的标准块大小为1,这导致需要很长时间才能通过非常大的搁置文件。文档建议分块而不是允许它一次发送1来加速它。
搁置模块不支持对搁置对象的并发读/写访问。 (多个同时读取访问是安全的。)当程序打开一个架子进行写入时,没有其他程序可以打开它进行读写。 Unix文件锁定可用于解决此问题,但这在Unix版本中有所不同,需要了解所使用的数据库实现。
最后,作为一个注释,我不确定您对多处理安全的假设是开箱即用的,具体取决于实现。
编辑:正如juanpa.arrivillaga所指出的那样,在this answer中它描述了后端发生了什么 - 你的整个可迭代可能正在被预先消耗,导致大量的内存使用。