TL;博士
根据 Valgrind 的 memcheck 工具,如果我在函数中分配一个大的局部变量并使用 启动该函数multiprocessing.Pool().apply_async()
,则子进程和主进程的堆大小都会增加。为什么 main 的堆大小会增加?
背景
我正在与一个多处理工作人员池一起工作,每个工作人员都将处理来自输入文件的大量数据。我想看看我的内存占用如何根据输入文件的大小进行缩放。为此,我在 Valgrind 下使用 memcheck 和此 SO answer中描述的技术运行我的脚本。(从那以后我了解到 Valgrind 的 Massif 工具更适合这个,所以我将使用它来代替。)
memcheck 输出中有一些看起来很奇怪的东西,我想帮助理解。
我在 Red Hat Linux 上使用 CPython 2.7.6,并像这样运行 memcheck:
valgrind --tool=memcheck --suppressions=./valgrind-python.supp python test.py
代码和输出
import multiprocessing
def mem_user():
tmp = 'a'*1
return
pool = multiprocessing.Pool(processes=1)
pool.apply_async(mem_user)
pool.close()
pool.join()
堆摘要(每个进程一个):
总堆使用量:45,193 分配,32,392 释放,7,221,910 字节分配
总堆使用:44,832 分配,22,006 释放,7,181,635 字节分配
如果我将tmp = 'a'*1
行更改为tmp = 'a'*10000000
我得到这些摘要:
总堆使用量:44,835 次分配,22,009 次释放,分配 27,181,763 字节
总堆使用量:45,195 次分配,32,394 次释放,分配 17,221,998 字节
问题
为什么两个进程的堆大小都会增加?我知道对象的空间是在堆上分配的,因此较大的堆对于其中一个进程当然是有意义的。但是我希望子进程拥有自己的堆、堆栈和解释器实例,所以我不明白为什么在子进程中分配的局部变量也会增加主进程的堆大小。如果它们共享同一个堆,那么 CPython 是否实现了自己的 fork() 版本,它不会为子进程分配唯一的堆空间?