Out of Memory Killer активиран за скрипт на python, изпълняващ многопроцесорна опашка?

Написах програма на Python, която трябва да работи няколко дни наведнъж, поради постоянното събиране на данни. Преди това нямах проблеми с тази програма в продължение на месеци. Наскоро направих някои актуализации на програмата и сега след около 12 часа получавам страховития убиец на паметта. Изходът "dmesg" е следният:

[9084334.914808] Out of memory: Kill process 2276 (python2.7) score 698 or sacrifice child
[9084334.914811] Killed process 2276 (python2.7) total-vm:13279000kB, anon-rss:4838164kB, file-rss:8kB

Освен общото кодиране на Python, основната промяна, направена в програмата, беше добавянето на опашка за многопроцесорна обработка. Това е първият път, когато използвам тази функция, така че не съм сигурен дали това може да е причината за проблема. Целта на опашката в моята програма е да може да прави динамични промени в паралелен процес. Опашката се инициира в основната програма и непрекъснато се наблюдава в паралелния процес. Опростена версия на това как правя това в паралелния процес е следната (като 'q' е опашката):

while(1):

    if q.empty():
        None

    else:
        fr = q.get()
        # Additional code

    time.sleep(1)

Динамичните промени на 'q' не се случват много често, така че по-голямата част от времето q.empty() ще бъде вярно, но цикълът е там, за да бъде готов веднага щом бъдат направени промените. Въпросът ми е дали изпълнението на този код за няколко часа наведнъж ще доведе до изчерпване на паметта? Тъй като цикълът „while“ е доста кратък и работи основно нон стоп, мислех, че това може да е проблем. Ако това може да е причината за проблема, някой има ли някакви предложения как да се подобри кодът, така че убиецът на недостиг на памет да не бъде извикан?

Благодаря ти много.


person rmsrms1987    schedule 27.02.2014    source източник
comment
if q.empty(): pass е идиоматичният начин за запис на този блок. Но би било още по-добре просто да имате if not q.empty(): fr = q.get() на първо място.   -  person Henry Keiter    schedule 27.02.2014
comment
Каква реализация използвате? .get() премахва ли елемента от опашката или само го инспектира? В последния случай размерът на опашката монотонно нараства.   -  person Stefano Sanfilippo    schedule 27.02.2014
comment
активиран ли е суап? какъв е резултатът от free?   -  person SingleNegationElimination    schedule 27.02.2014
comment
Благодаря ви за всички коментари. Начинът, по който използвам .get(), е да премахна списък от опашката. Така че използвам .put() в основната програма, за да изпратя списъка към паралелния процес и .get() е това, което го взима. По-рано предположих, че след въвеждане на .get() опашката се изчиства, но може би греша.   -  person rmsrms1987    schedule 27.02.2014
comment
Спрях да изпълнявам програмата преди известно време, но ето текущия изход на 'free': общо използвани безплатни споделени буфери, кеширани Mem: 8177396 1659060 6518336 0 255036 560160 -/+ буфери/кеш: 843864 7333532 Размяна: 10027004 869020 915 7984   -  person rmsrms1987    schedule 27.02.2014
comment
Опитахте ли да промените /proc/‹pid›/oom_score за вашия процес?   -  person Alexander Gryanko    schedule 28.02.2014


Отговори (2)


Единственият начин да останете без памет по начина, който описвате, е ако използвате все повече и повече памет с течение на времето. Цикълът тук не демонстрира това поведение, така че не може да бъде (единствено) отговорен за грешки в паметта. Изпълнението на стегнат, безкраен цикъл може да изгори много ненужни цикли на процесора, но не може да причини MemoryError само по себе си, освен ако не съхранява данни на друго място.

Вероятно другаде в кода ви задържате някои променливи, които не възнамерявате. Това се нарича изтичане на памет и можете да използвате профайлър на памет, за да търсите откъде идва това изтичане.

Някои вероятни заподозрени са методи за кеширане, използвани за подобряване на производителността, или списъци с променливи, които никога не излизат от обхвата. Може би вашата многопроцесорна опашка задържа препратки към по-ранни обекти с данни или елементите никога не се изтриват от опашката, след като бъдат вмъкнати? (Последният случай е малко вероятен предвид кода, който сте показали, ако използвате вградения queue.Queue, но всичко е възможно).

person Henry Keiter    schedule 27.02.2014
comment
Това не е отговор. Публикувайте го като коментар. - person Stefano Sanfilippo; 27.02.2014
comment
@Stefano Как това не е отговор? "My question is, would running this code for multiple hours at a time cause the memory to eventually run low?" Отговорът е Не, даденият код не може да доведе до изчерпване на паметта на програмата. - person Henry Keiter; 27.02.2014
comment
Вашият отговор гласи: Не мога да заключа, че кодът ви причинява тази грешка сам по себе си, моля, предоставете повече подробности. Това бих написал в коментар. И това парче (псевдо)код може да е причината, защото не знаете поведението на queue.get. - person Stefano Sanfilippo; 27.02.2014
comment
@Stefano Предполагам, поради липса на друга информация, че той използва queue.Queue, което не би причинило това поведение. Питащият не ни помоли да намерим изтичането на памет, а по-скоро дали може да е причинено от тесния цикъл в паралелен процес. Все пак редактирах отговора си, за да се надявам да чета по-малко като искане за повече информация. - person Henry Keiter; 27.02.2014
comment
Въпросът не е строго ограничен до цикъла, изпълнението на този код за няколко часа наведнъж ще доведе ли до изчерпване на паметта?. И програмистите трябва да се пазят от предположения. Когато се съмнявате, попитайте ОП. - person Stefano Sanfilippo; 27.02.2014

Можете да конвертирате вашата програма в услуга на linux и да зададете политиката й за oom да продължи.

Можете да проверите това и тази връзки, за да видите как да виждате/редактирате параметрите на услугата и съответно да видите параметъра на услугата за правилата на oom.

person zenprogrammer    schedule 10.08.2020