2016-09-28 9 views
5

Próbuję użyć setrlimit, aby ograniczyć wykorzystanie pamięci w systemie Linux, aby zatrzymać proces przed awarią komputera (mój kod powodował awarię węzłów w klastrze o wysokiej wydajności, ponieważ błąd doprowadził do zużycia pamięci przekraczającej 100 GiB). Nie mogę znaleźć odpowiedniego zasobu do przekazania setrlimit; Myślę, że powinno być miejsce zamieszkania, które cannot be limited with setrlimit, ale jestem zdezorientowany przez rezydenta, kupa, stos. W poniższym kodzie; gdybym odkomentowaniu tylko RLIMIT_AS, kod nie działa z MemoryError w numpy.ones(shape=(1000, 1000, 10), dtype="f8") mimo że tablica powinna być tylko 80 MB. Gdybym odkomentowaniu tylko RLIMIT_DATA, RLIMIT_RSS lub RLIMIT_STACK obie tablice uzyskać przydzielone powodzeniem, chociaż całkowite użycie pamięci 2 GB, lub dwukrotnie żądany maksymalny.Jak używać `setrlimit` do ograniczania zużycia pamięci? RLIMIT_AS zabija za wcześnie; RLIMIT_DATA, RLIMIT_RSS, RLIMIT_STACK zabijają w ogóle

Chciałbym, aby uczynić mój program nie (nie ważne jak) tak szybko, jak to próbuje przeznaczyć zbyt dużo pamięci RAM. Dlaczego żaden z RLIMIT_DATA, RLIMIT_RSS, RLIMIT_STACK i RLIMIT_AS robić to, co mam na myśli, a co to jest poprawny zasób, aby przejść do setrlimit?

$ cat mwe.py 
#!/usr/bin/env python3.5 

import resource 
import numpy 

#rsrc = resource.RLIMIT_AS 
#rsrc = resource.RLIMIT_DATA 
#rsrc = resource.RLIMIT_RSS 
#rsrc = resource.RLIMIT_STACK 

soft, hard = resource.getrlimit(rsrc) 
print("Limit starts as:", soft, hard) 

resource.setrlimit(rsrc, (1e9, 1e9)) 

soft, hard = resource.getrlimit(rsrc) 
print("Limit is now:", soft, hard) 
print("Allocating 80 KB, should certainly work") 
M1 = numpy.arange(100*100, dtype="u8") 

print("Allocating 80 MB, should work") 
M2 = numpy.arange(1000*1000*10, dtype="u8") 

print("Allocating 2 GB, should fail") 
M3 = numpy.arange(1000*1000*250, dtype="u8") 

input("Still here…") 

Wyjście z linią RLIMIT_AS Odkomentowano:

$ ./mwe.py 
Limit starts as: -1 -1 
Limit is now: 1000000000 -1 
Allocating 80 KB, should certainly work 
Allocating 80 MB, should work 
Traceback (most recent call last): 
    File "./mwe.py", line 22, in <module> 
    M2 = numpy.arange(1000*1000*10, dtype="u8") 
MemoryError 

wyjścia, gdy uruchomiony z którykolwiek z nich komentarzem:

$ ./mwe.py 
Limit starts as: -1 -1 
Limit is now: 1000000000 -1 
Allocating 80 KB, should certainly work 
Allocating 80 MB, should work 
Allocating 2 GB, should fail 
Still here… 

W końcowej linii top donosi, że mój proces jest przy użyciu 379 GB VIRT, 2,0 GB OZE.


dane systemowe:

$ uname -a 
Linux host.somewhere.ac.uk 2.6.32-573.3.1.el6.x86_64 #1 SMP Mon Aug 10 09:44:54 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux 

$ cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 6.7 (Santiago) 

$ free -h 
      total  used  free  shared buffers  cached 
Mem:   2.0T  1.9T  37G  1.6G  3.4G  1.8T 
-/+ buffers/cache:  88G  1.9T 
Swap:   464G  4.8M  464G 

$ python3.5 --version 
Python 3.5.0 

$ python3.5 -c "import numpy; print(numpy.__version__)" 
1.11.1 
+0

Możliwy duplikat [Setting stacksize w skrypcie Pythona] (https://stackoverflow.com/questions/5061582/setting-stacksize-in-a-python-script) – jww

+0

próbuje ustawić 'rlimit_stack' po [ Clash stos] (http://www.openwall.com/lists/oss-security/2017/06/19/1) remediations może prowadzić do awarii lub problemów związanych. Zobacz także Red Hat [numer 1463241] (https://bugzilla.redhat.com/show_bug.cgi?id=1463241) – jww

Odpowiedz

1

Niestety nie mam odpowiedź na swoje pytanie. Mam jednak nadzieję, że poniższe informacje mogą pomóc:

  • Twój skrypt działa zgodnie z oczekiwaniami w moim systemie. Proszę podać dokładną specyfikację dla twojej, może być znany problem z dystrybucją Linuksa, jądrem lub nawet numpy ...
  • Powinieneś być w porządku z RLIMIT_AS. Jak wyjaśnił here, powinno to ograniczyć całą pamięć wirtualną używaną przez proces. A pamięć wirtualna obejmuje wszystkie: pamięć wymiany, biblioteki współdzielone, kod i dane. Więcej szczegółów here.
  • Możesz dodać następującą funkcję (przyjęty z this answer) do skryptu, aby sprawdzić rzeczywiste zużycie pamięci wirtualnej w dowolnym momencie:

    def peak_virtual_memory_mb(): 
        with open('/proc/self/status') as f: 
         status = f.readlines() 
         vmpeak = next(s for s in status if s.startswith("VmPeak:")) 
         return vmpeak 
    
  • Ogólna rada wyłączyć pamięć wymiany. Z mojego doświadczenia z serwerami o wysokiej wydajności robi więcej szkód niż rozwiązuje problemy.
+0

Dodałem pewne szczegóły systemu. Czy muszę dodać więcej? 'top' zgłasza, że ​​używam 379 GB pamięci wirtualnej.Nie wiem dlaczego, ale prawdopodobnie wyjaśnia, dlaczego wersja "RLIMIT_AS" zawodzi wcześniej. Uwaga: jestem tylko użytkownikiem tego serwera i nie mogę wyłączyć pamięci wymiany. – gerrit

+0

Tak, rzeczywiście 379GB jest naprawdę dziwne i może wyjaśnić wczesną awarię. Jaki smak Linuksa działa na komputerze? Czy próbowałeś 'print peak_virtual_memory_mb()' przed i po alokacji pamięci? BTW, prawdopodobnie najlepiej nie udostępniać nazwy hosta na publicznej stronie :) –

+0

@ To Redhat Enterprise Linux (patrz edycja). Nie wiem, jak wydrukować szczytową pamięć wirtualną. – gerrit

Powiązane problemy