[英]Python multiprocessing--global variables in separate processes sharing id?
從這個問題中我了解到:
當您使用多重處理打開第二個進程時,將創建一個具有自己全局狀態的Python全新實例。 該全局狀態不會共享,因此子進程對全局變量所做的更改對於父進程將是不可見的。
為了驗證此行為,我做了一個測試腳本:
import time
import multiprocessing as mp
from multiprocessing import Pool
x = [0] # global
def worker(c):
if c == 1: # wait for proc 2 to finish; is global x overwritten by now?
time.sleep(2)
print('enter: x =', x, 'with id', id(x), 'in proc', mp.current_process())
x[0] = c
print('exit: x =', x, 'with id', id(x), 'in proc', mp.current_process())
return x[0]
pool = Pool(processes=2)
x_vals = pool.map(worker, [1, 2])
print('parent: x =', x, 'with id', id(x), 'in proc', mp.current_process())
print('final output', x_vals)
輸出(在CPython上)類似於
enter: x = [0] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-2, started daemon)>
exit: x = [2] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-2, started daemon)>
enter: x = [0] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-1, started daemon)>
exit: x = [1] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-1, started daemon)>
parent: x = [0] with id 140138406834504 in proc <_MainProcess(MainProcess, started)>
final output [1, 2]
我應該如何解釋x
的id
在所有進程中共享但x
取不同值的事實? 從概念上講, id
不是Python對象的內存地址嗎? 我想如果在子進程中克隆內存空間,這是可能的。 那有什么我可以用來獲取Python對象的實際物理內存地址的東西嗎?
共享狀態
當您使用多重處理打開第二個進程時,將創建一個具有自己全局狀態的Python全新實例。 該全局狀態不會共享,因此子進程對全局變量所做的更改對於父進程將是不可見的。
這里的關鍵點似乎是:
這種全球狀態不會共享...”
... 指的是子進程的全局狀態。 但這並不意味着父級的全局狀態的一部分不能與子進程共享,只要子進程不嘗試寫入該部分。 發生這種情況時,將復制並更改此部分獲取,並且父級將看不到該部分。
背景:
在Unix上, “ fork”是啟動子進程的默認方式:
父進程使用os.fork()派生Python解釋器。 子進程開始時實際上與父進程相同。 父進程的所有資源均由子進程繼承。 請注意,安全地分叉多線程進程是有問題的。
僅在Unix上可用。 Unix上的默認值。
Fork是使用寫時復制實現的,因此除非您為x
分配新對象,否則不會進行復制,並且子進程與其父進程共享相同的列表。
內存地址
我應該如何解釋x的ID在所有進程中共享但x取不同值的事實?
Fork創建一個子進程,其中虛擬地址空間與父進程的虛擬地址空間相同。 虛擬地址將全部映射到相同的物理地址,直到發生寫時復制。
現代操作系統使用虛擬尋址。 基本上,您在程序內部看到的地址值(指針)不是實際的物理內存位置,而是指向索引表(虛擬地址)的指針,而索引表又包含指向實際的物理內存位置的指針。 由於這種間接方式,如果虛擬地址屬於不同進程的索引表,則可以將同一虛擬地址指向不同的物理地址。 鏈接
那有什么我可以用來獲取Python對象的實際物理內存地址的東西嗎?
似乎沒有辦法獲取實際的物理內存地址( link )。 id
返回虛擬 (邏輯)內存地址(CPython)。 從虛擬內存到物理內存地址的實際轉換屬於MMU 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.