Implementuję algorytm przeszukiwania wykresów Strong Connected Component (SCC) Kosaraju w Pythonie.
Program działa świetnie na małym zestawie danych, ale kiedy uruchamiam go na bardzo dużym wykresie (ponad 800 000 węzłów), wyświetla komunikat „Błąd segmentacji”.
Jaka może być tego przyczyna? Dziękuję Ci!
Dodatkowe informacje: Najpierw otrzymałem ten błąd podczas pracy na bardzo dużym zestawie danych:
"RuntimeError: maximum recursion depth exceeded in cmp"
Następnie zresetowałem limit rekursji za pomocą
sys.setrecursionlimit(50000)
ale otrzymałem „błąd segmentacji”
Uwierz mi, to nie jest nieskończona pętla, działa poprawnie na stosunkowo mniejszych danych. Czy możliwe, że program wyczerpał zasoby?
python
segmentation-fault
large-data
xiaolong
źródło
źródło
Odpowiedzi:
Dzieje się tak, gdy rozszerzenie Pythona (napisane w C) próbuje uzyskać dostęp do pamięci poza zasięgiem.
Możesz to prześledzić na następujące sposoby.
sys.settrace
w pierwszym wierszu kodu.Użyj w
gdb
sposób opisany przez Marka w tej odpowiedzi .. W wierszu poleceniagdb python (gdb) run /path/to/script.py ## wait for segfault ## (gdb) backtrace ## stack trace of the c code
źródło
Rozumiem, że rozwiązałeś swój problem, ale dla innych czytających ten wątek odpowiedź jest następująca: musisz zwiększyć stos, który Twój system operacyjny przydziela dla procesu Pythona.
Sposób na to zależy od systemu operacyjnego. W Linuksie możesz sprawdzić za pomocą polecenia
ulimit -s
swoją aktualną wartość i możesz ją zwiększyć za pomocąulimit -s <new_value>
Spróbuj podwoić poprzednią wartość i kontynuuj podwajanie, jeśli to nie zadziała, aż znajdziesz taką, która działa lub zabraknie jej pamięci.
źródło
lsof
i używaniegrep
lubwc -l
śledzenie wszystkiego.Błąd segmentacji ma charakter ogólny, istnieje wiele możliwych przyczyn:
źródło
Aktualizacja ulimit zadziałała dla mojej implementacji SCC w Kosaraju, naprawiając błąd segfault w implementacjach Pythona (Python segfault… kto wiedział!) I C ++.
W przypadku mojego MAC znalazłem możliwe maksimum poprzez:
$ ulimit -s -H 65532
źródło
Wyszukiwarka Google znalazła ten artykuł i nie widziałem omówionego następującego „rozwiązania osobistego”.
Moją ostatnią irytacją związaną z Pythonem 3.7 w podsystemie Windows dla systemu Linux jest to, że: na dwóch komputerach z tą samą biblioteką Pandas, jeden daje mi
segmentation fault
ostrzeżenie, a drugi zgłasza. Nie było jasne, który z nich jest nowszy, ale „ponowna instalacja”pandas
rozwiązuje problem.Rozkaz, że uruchomiłem na buggy machine.
Więcej szczegółów: uruchamiałem identyczne skrypty (zsynchronizowane przez Git) i oba są maszynami Windows 10 z WSL + Anaconda. Oto zrzuty ekranu, aby złożyć sprawę. Ponadto na komputerze, na który
python
będzie narzekać wiersz poleceńSegmentation fault (core dumped)
, laboratorium Jupyter po prostu restartuje jądro za każdym razem. Co gorsza, nie było żadnego ostrzeżenia.Aktualizacje kilka miesięcy później: przestałem hostować serwery Jupyter na komputerze z systemem Windows. Teraz używam WSL w systemie Windows do pobierania zdalnych portów otwartych na serwerze Linux i uruchamiania wszystkich moich zadań na zdalnym komputerze z systemem Linux. Nigdy nie doświadczyłem żadnego błędu wykonania przez dobrą liczbę miesięcy :)
źródło
Wystąpił ten błąd segmentacji po uaktualnieniu dlib na RPI. Prześledziłem stos, jak zasugerował Shiplu Mokaddim powyżej, i ustaliłem na podstawie biblioteki OpenBLAS.
Ponieważ OpenBLAS jest również wielowątkowy, użycie go w aplikacji wielowątkowej spowoduje wykładnicze mnożenie wątków aż do błędu segmentacji. W przypadku aplikacji wielowątkowych ustaw OpenBlas na tryb jednowątkowy.
W środowisku wirtualnym Pythona powiedz OpenBLAS, aby używał tylko jednego wątku, edytując:
$ workon <myenv> $ nano .virtualenv/<myenv>/bin/postactivate
i dodaj:
export OPENBLAS_NUM_THREADS=1 export OPENBLAS_MAIN_FREE=1
Po ponownym uruchomieniu mogłem uruchomić wszystkie aplikacje do rozpoznawania obrazu na rpi3b, które wcześniej go zawieszały.
źródło: https://github.com/ageitgey/face_recognition/issues/294
źródło
Wygląda na to, że zabrakło pamięci stosu. Możesz chcieć go zwiększyć, jak stwierdził Davide. Aby to zrobić w kodzie Pythona, musiałbyś uruchomić swoją "main ()" używając wątków:
def main(): pass # write your code here sys.setrecursionlimit(2097152) # adjust numbers threading.stack_size(134217728) # for your needs main_thread = threading.Thread(target=main) main_thread.start() main_thread.join()
Źródło: post c1729 o codeforsces . Uruchomienie go z PyPy jest nieco trudniejsze .
źródło