POSIX सिस्टम पर, आपके द्वारा कांटा () के बाद, डेटा को केवल आपके द्वारा इसे लिखने के बाद चाइल्ड प्रोसेस में कॉपी किया जाना चाहिए (लिखने पर कॉपी करें)। लेकिन चूंकि पाइथन ऑब्जेक्ट हेडर में संदर्भ गणना संग्रहीत करता है, हर बार जब आप बच्चे की प्रक्रिया में एक सूची को पुन: सक्रिय करते हैं, तो यह इसे अपनी स्मृति में कॉपी कर देगा।

परीक्षण करना कि सूचियों और अन्य डेटा संरचनाओं के साथ, मैं उस व्यवहार पर जोर दे सकता हूं, कोर डेवलपर से कुछ पुष्टि भी: https://github.com/python/cpython/pull/3705#issuecomment- ४२०२०१०७१

लेकिन परीक्षण के बाद कि numpy arrays के साथ, ऐसा नहीं हो रहा है।

import ctypes
import os

import numpy as np
import psutil


def sharing_with_numpy():
    ppid = os.getpid()
    print(f'\nSystem used memory: {int(psutil.virtual_memory().used / (1024 * 1024))} MB')
    big_data = np.array([[item, item] for item in list(range(10000000))])
    print(f'\nSystem used memory: {int(psutil.virtual_memory().used / (1024 * 1024))} MB')
    print(ctypes.c_long.from_address(id(big_data)).value)
    ref1 = big_data[0]
    ref2 = big_data[0]
    print(ctypes.c_long.from_address(id(big_data)).value)

    print(f'\nSystem used memory: {int(psutil.virtual_memory().used / (1024 * 1024))} MB')
    for i in range(5):
        if ppid == os.getpid():
            os.fork()
    for x in big_data:
        pass
    print(f'\nSystem used memory: {int(psutil.virtual_memory().used / (1024 * 1024))} MB')


if __name__ == "__main__":
    sharing_with_numpy()

आउटपुट:

System used memory: 163 MB # before array allocation
System used memory: 318 MB # after array allocation
1 # reference count of the array
3 # reference count of the array
System used memory: 318 MB # before fork()
System used memory: 324 MB # after fork() and loop to reference array
System used memory: 328 MB # after fork() and loop to reference array
System used memory: 329 MB # after fork() and loop to reference array
System used memory: 331 MB # after fork() and loop to reference array
System used memory: 340 MB # after fork() and loop to reference array
System used memory: 342 MB # after fork() and loop to reference array

जैसा कि आप देख सकते हैं, स्मृति बढ़ती है, लेकिन केवल थोड़ा, यह दर्शाता है कि संपूर्ण सरणी की प्रतिलिपि नहीं बनाई गई थी।

मैं यह समझने की कोशिश कर रहा हूं कि भाग्य के बिना क्या हो रहा है, क्या आप समझा सकते हैं? शुक्रिया

1
lsena 31 जिंदा 2021, 19:10

1 उत्तर

सबसे बढ़िया उत्तर

numpy सरणियों में एक ऑब्जेक्ट हेडर होता है जिसमें अंतर्निहित डेटा के लिए एक पॉइंटर होता है, जिसे अलग से आवंटित किया जाता है। डेटा में ही कोई संदर्भ संख्या नहीं है, इसलिए इसे केवल इसे पढ़ने से संशोधित नहीं किया जाता है।

चूंकि numpy सरणियों को थोक में ब्लॉक आवंटित किया जाता है, डेटा स्टोर के समर्थन के लिए बड़ा आवंटन ऑब्जेक्ट हेडर से आने वाले छोटे ऑब्जेक्ट पूल से नहीं आता है (वे आम तौर पर ओएस से सीधे थोक आवंटित होते हैं, के माध्यम से mmap [*NIX] या VirtualAlloc [Windows], कई आवंटनों में विभाजित स्मृति के ढेर से आवंटित नहीं)। चूंकि वे कुछ भी के साथ एक पृष्ठ साझा नहीं करते हैं, जिसका संदर्भ गिना जाता है (वे कच्चे सी प्रकार हैं, न कि पायथन ints या अपने स्वयं के ऑब्जेक्ट हेडर के साथ पसंद करते हैं), वे पृष्ठ कभी लिखे नहीं जाते, और इसलिए कभी कॉपी नहीं होते।

2
ShadowRanger 1 फरवरी 2021, 01:13
ठीक है, यह समझ में आता है और यह जांचता है, धन्यवाद!
 – 
lsena
2 फरवरी 2021, 01:13