我正在运行一个程序,首先将20 GB的数据加载到内存中。然后,我将执行N(> 1000)个独立的任务,每个任务可能会使用(只读)20 GB数据的一部分。现在我正在尝试通过多进程来执行这些任务。但是,正如这个答案所说,每个进程都会复制整个全局变量。在我的情况下,由于我的内存只有96 GB,无法执行超过4个任务。我想知道是否有解决这种问题的方法,以便我可以充分利用所有的核心而不消耗太多内存。
我正在运行一个程序,首先将20 GB的数据加载到内存中。然后,我将执行N(> 1000)个独立的任务,每个任务可能会使用(只读)20 GB数据的一部分。现在我正在尝试通过多进程来执行这些任务。但是,正如这个答案所说,每个进程都会复制整个全局变量。在我的情况下,由于我的内存只有96 GB,无法执行超过4个任务。我想知道是否有解决这种问题的方法,以便我可以充分利用所有的核心而不消耗太多内存。
import os
var = "unchanged"
pid = os.fork()
if pid:
print('parent:', os.getpid(), var)
os.waitpid(pid, 0)
else:
print('child:', os.getpid(), var)
var = "changed"
# show parent and child views
print(os.getpid(), var)
结果在
parent: 22642 unchanged
child: 22643 unchanged
22643 changed
22642 unchanged
将这个应用到多进程中,在这个例子中我将数据加载到全局变量中。由于Python会对发送到进程池的数据进行序列化,因此我确保它只序列化一些小的内容,如索引,并让工作者自己获取全局数据。
import multiprocessing as mp
import os
my_big_data = "well, bigger than this"
def worker(index):
"""get char in big data"""
return my_big_data[index]
if __name__ == "__main__":
pool = mp.Pool(os.cpu_count())
for c in pool.imap_unordered(worker, range(len(my_big_data)), chunksize=1):
print(c)
在Windows中,没有像fork-and-exec模型那样运行程序。它必须启动一个新的Python解释器实例,并将所有相关数据克隆到子进程中。这是一项沉重的任务!
mp
的内容时会感到几件事情相互矛盾。感谢您的解释,点赞。出于好奇,由于Windows的限制,我仍然被迫使用“管理器”;在我的情况下,这是否会首先创建另一个20GB的对象(原始+“管理器”=40GB)以初始化共享资源?文档表明,进程通过代理访问共享列表/字典到_Manager_,但我从未在mp
中处理过足够大的数据来进行测试。 - roganjoshmap
和imap
都会等待所有处理完成并按提交顺序返回结果。如果您不关心返回顺序,则imap_unordered
更有效,并且如果结果很大,它将使用更少的内存。在Python 2.x和3.x中,多进程处理基本相同。根据您是否需要有序结果,map
和imap_unordered
都是不错的选择。 - tdelaneyManager
是如何实现的,但那些代理对象对我来说似乎很重。在Windows中,如果您可以使用共享内存或内存映射文件,我认为您会更好。但这意味着像列表(它们分散在整个内存中)这样的东西是一个问题。从哲学上讲,Windows 更喜欢线程而不是轻量级子进程,但这与 Python GIL 模型相矛盾。 - tdelaney
Manager.dict()
here或Manager.list()
中共享数据并生成多个Processes
。如果它们都在执行相同的任务,则可以将数据分块并将每个进程分配到自己的块。我认为您不能有用地生成比核心更多的进程,而且似乎您想要>1000
个进程? - roganjoshManager
对我来说是解决方法,无论我需要读取还是写入访问权限。我将不得不再次尝试在Linux上使用这种方法。 - roganjoshj = multiprocessing.Process(target=getDV04CclDrivers, args=('LORR', dataDV04))
... 即使dataDV04
是全局的,他仍然将其作为参数传递,因此即使在Linux情况下也需要进行pickle。 - tdelaney