Käyttelemme Pythonia melko paljon Zendeskin palvelimella, kun rakennamme koneenoppimis- (ML-) tuotteita. Yksi yleisimmistä suorituskykyongelmista, joihin törmäsimme koneoppimissovellusten kanssa, on muistivuodot ja -piikit. Python-koodi suoritetaan yleensä konteissa hajautettujen käsittelykehysten, kuten Hadoopin, Sparkin ja AWS Batchin, kautta. Jokaiselle kontille varataan kiinteä määrä muistia. Kun koodin suoritus ylittää määritellyn muistirajan, kontti lopetetaan muistin loppumiseen liittyvien virheiden vuoksi.
Pikaratkaisu on lisätä muistin varausta. Tämä voi kuitenkin johtaa resurssien tuhlaamiseen ja vaikuttaa tuotteiden vakauteen arvaamattomien muistipiikkien vuoksi. Muistivuodon syitä voivat olla muun muassa:
- suurten objektien sitominen, joita ei vapauteta
- viittaussyklit koodissa
- koodin taustalla olevat kirjastot/C-laajennukset, jotka vuotavat muistia
Hyödyllinen harjoitus on profiloida sovellusten muistinkäyttö, jotta saadaan parempi käsitys koodin ja sen taustalla olevien käytettävien pakettien tilatehokkuudesta. Tässä postauksessa käsitellään:
- sovelluksen muistinkäytön profilointi ajassa
- miten tarkastellaan muistinkäyttöä ohjelman tietyssä osassa
- vinkkejä muistiongelmien vianmääritykseen
Muistiprofiilipaketin avulla voit tarkastella muistinkäytön vaihtelua ajassa Python-koodin suorituksen aikana.
# install the required packages
pip install memory_profiler
pip install matplotlib# run the profiler to record the memory usage
# sample 0.1s by defaut
mprof run --include-children python fantastic_model_building_code.py# plot the recorded memory usage
mprof plot --output memory-profile.png
Vaihtoehto include-children sisältää kaikkien emoprosessin kautta poikineiden lapsiprosessien muistinkäytön. Kuvaajassa A näkyy iteratiivinen mallin koulutusprosessi, joka aiheuttaa muistin lisääntymisen sykleittäin, kun koulutusdatan eriä käsitellään. Objektit vapautetaan, kun roskienkeräys käynnistyy.
Jos muistin käyttö kasvaa jatkuvasti, on olemassa mahdollinen ongelma muistivuodoista. Tässä on tyhmä esimerkkiskripti havainnollistamaan tätä.
Vianmäärityksen taukopiste voidaan asettaa, kun muistin käyttö ylittää tietyn kynnysarvon, käyttämällä optiota pdb-mmem, joka on kätevä vianmäärityksessä.
Muistityhjennys tiettynä ajankohtana
On tärkeää ymmärtää ohjelmassa olevien suurten objektien odotettavissa oleva määrä ja se, pitäisikö niitä monistaa ja/tai muuntaa eri muotoihin.
Muistissa olevien objektien tarkemmaksi analysoimiseksi voidaan muppy-ohjelmalla luoda heap-dumppi tiettyjen ohjelmakoodirivien aikana.
Toinen hyödyllinen muistin profiloinnin mahdollistava kirjasto on objgraph, joka voi luoda objektien grafiikoita, joiden avulla voidaan tarkastaa objektien linjat.
Pyrkimys nopeaan palautesilmukkaan
Hyödyllinen lähestymistapa on pienen ”testitapauksen” luominen, jossa ajetaan vain kyseistä muistivuotokoodia. Harkitse osajoukon käyttämistä satunnaisesti poimitusta datasta, jos koko syötedatan ajaminen on pitkäkestoista.
Käynnistä muistia vaativat tehtävät erillisessä prosessissa
Python ei välttämättä vapauta muistia heti takaisin käyttöjärjestelmälle. Jotta voidaan varmistaa, että muisti vapautuu koodin suorituksen jälkeen, sitä on ajettava erillisessä prosessissa. Tällä sivulla on lisätietoja Pythonin roskienkeruusta.
Debuggeri voi lisätä viittauksia objekteihin
Jos käytetään breakpoint-debuggeria, kuten pdb:tä, kaikki objekteja, jotka on luotu ja joihin viitataan manuaalisesti debuggerista, jäävät muistiprofiiliin. Tämä voi luoda vääränlaisen tunteen muistivuodoista, jolloin objekteja ei vapauteta ajoissa.
Varo paketteja, jotka voivat olla vuotavia
Joissain Python-kirjastoissa voi mahdollisesti olla muistivuotoja. Esim. pandasilla on melko paljon tunnettuja muistivuoto-ongelmia.
Hyvää metsästystä!