/ / numpy.Vyberané objekty nie sú zbierané - python, správa pamäte, úniky pamäte, zber odpadu, profilovanie pamäte

numpy.ndarray objekty, ktoré nie sú zhromaždené - python, správa pamäte, úniky pamäte, zber odpadu, pamäťový profil

Pri pokusoch o jemné vyladenie niektorých netesností pamäte v väzbách Pythonu pre niektoré funkcie C / C ++ narazím na nejaké podivné správanie týkajúce sa zbierky odpadkov Numpy polí.

Vytvoril som niekoľko zjednodušených prípadov, aby som lepšie vysvetlil svoje správanie. Kód bol spustený pomocou memory_profiler, výstup, z ktorého vyplýva bezprostredne potom. Zdá sa, že zbierka odpadkov Pythonu nefunguje podľa očakávaní, pokiaľ ide o polia NumPy:

# File deallocate_ndarray.py
@profile
def ndarray_deletion():
import numpy as np
from gc import collect
buf = "abcdefghijklmnopqrstuvwxyz" * 10000
arr = np.frombuffer(buf)
del arr
del buf
collect()
y = [i**2 for i in xrange(10000)]
del y
collect()

if __name__=="__main__":
ndarray_deletion()

Nasledujúcim príkazom som vyvolala memory_profiler:

python -m memory_profiler deallocate_ndarray.py

To je to, čo som dostal:

Filename: deallocate_ndarray.py
Line #    Mem usage    Increment   Line Contents
================================================
5   10.379 MiB    0.000 MiB   @profile
6                             def ndarray_deletion():
7   17.746 MiB    7.367 MiB       import numpy as np
8   17.746 MiB    0.000 MiB       from gc import collect
9   17.996 MiB    0.250 MiB       buf = "abcdefghijklmnopqrstuvwxyz" * 10000
10   18.004 MiB    0.008 MiB       arr = np.frombuffer(buf)
11   18.004 MiB    0.000 MiB       del arr
12   18.004 MiB    0.000 MiB       del buf
13   18.004 MiB    0.000 MiB       collect()
14   18.359 MiB    0.355 MiB       y = [i**2 for i in xrange(10000)]
15   18.359 MiB    0.000 MiB       del y
16   18.359 MiB    0.000 MiB       collect()

Nerozumiem, prečo aj nútené volania collect neznížite využitie pamäte programomuvoľnenie nejakej pamäte. Navyše, aj keď sa Numpy polia nechovajú normálne kvôli základným C konštruktom, prečo sa tento zoznam (čo je čistý Python) nezhromažďuje?

viem že del priamo nenazýva podkladové __del__ metóda, ale všimnete si to všetko del tvrdenia v kóde skutočne skončia znižovanímreferenčný počet zodpovedajúcich predmetov na nulu (čím sa stáva oprávneným na zber odpadkov AFAIK). Obvykle by som očakával negatívny záznam v stĺpci prírastkov, keď sa objekt podrobí zberu odpadu. Môže niekto objasniť, čo sa tu deje?

POZNÁMKA: Tento test sa uskutočnil na OS X 10.10.4, Python 2.7.10 (conda), Numpy 1.9.2 (conda), Memory Profiler 0.33 (conda-binstar), psutil 2.2.1 (conda).

odpovede:

3 pre odpoveď č. 1

Aby som videl zhromaždené odpadky z pamäte, musel som zväčšiť veľkosť bufu o niekoľko rádov. Možno je veľkosť príliš malá memory_profiler na detekciu zmeny (pýta sa na OS, takže merania nie sú príliš presné) alebo možno je príliš malá na to, aby sa mohla zberateľ odpadu Python postarať, neviem.

Napríklad nahradenie faktora 10000 číslom 100000000 buf výťažky

Line #    Mem usage    Increment   Line Contents
================================================
21   10.289 MiB    0.000 MiB   @profile
22                             def ndarray_deletion():
23   17.309 MiB    7.020 MiB       import numpy as np
24   17.309 MiB    0.000 MiB       from gc import collect
25 2496.863 MiB 2479.555 MiB       buf = "abcdefghijklmnopqrstuvwxyz" * 100000000
26 2496.867 MiB    0.004 MiB       arr = np.frombuffer(buf)
27 2496.867 MiB    0.000 MiB       del arr
28   17.312 MiB -2479.555 MiB       del buf
29   17.312 MiB    0.000 MiB       collect()
30   17.719 MiB    0.406 MiB       y = [i**2 for i in xrange(10000)]
31   17.719 MiB    0.000 MiB       del y
32   17.719 MiB    0.000 MiB       collect()