簡體   English   中英

為什么局部於Python子進程的對象分配會增加main的堆大小?

[英]Why does an object allocation local to a Python subprocess increase heap size for main?

TL; DR

根據Valgrind的memcheck工具,如果我在一個函數中分配一個較大的局部變量並使用multiprocessing.Pool().apply_async()啟動該函數,則子進程和主進程的堆大小都會增加。 為什么main的堆大小會增加?

背景

我正在與一個多進程工作池一起工作,每個工作人員都將處理輸入文件中的大量數據。 我想看看我的內存占用量如何根據輸入文件的大小縮放。 為此,我使用memcheck和此SO Answer中描述的技術在Valgrind下運行了腳本。 (此后,我了解到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字節分配

問題

為什么兩個進程的堆大小都會增加? 我知道對象的空間是在堆上分配的 ,因此較大的堆對於其中一個進程當然是有意義的。 但是我希望子進程具有自己的堆,堆棧和解釋器實例,所以我不明白為什么在子進程中分配的局部變量也會增加main的堆大小。 如果它們共享相同的堆,那么CPython是否實現自己的fork()版本,該版本不會為子進程分配唯一的堆空間?

問題與fork的實現方式無關。 您可以自己看到, multiprocessing調用os.fork ,這是一個非常薄的fork封裝。

那么,這怎么回事?

編譯器看到源代碼中的'a' * 10000000並將其優化為10000000個字符的文字。 這意味着模塊對象現在要長10000000字節,並且由於在兩個進程中都將其導入,因此它們都變得更大。

要看到這個:

$ python2.7
>>> def f():
...     temp = 'a' * 10
...
>>> f.__code__.co_consts
(None, 'a', 10, 'aaaaaaaaaa')
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_CONST               3 ('aaaaaaaaaa')
              3 STORE_FAST               0 (temp)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE

請注意,編譯器足夠聰明,可以將'aaaaaaaaaa'添加到常量中,但是不足以刪除'a'10 那是因為它使用了非常狹窄的窺孔優化器。 除了它不知道您是否還在同一函數中的其他位置使用'a'這一事實外,它還不想從co_consts列表的中間刪除一個值,然后返回並更新所有其他字節碼為使用上移的索引。


我實際上不知道為什么子級最終以20000000個字節而不是10000000個字節增長。大概它以其自己的模塊或至少代碼對象的副本結尾,而不是使用父級共享的副本。 但是,如果我嘗試print id(f.__code__)或其他任何內容,那么我在父級和子級中會得到相同的值,所以……

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM