파이썬 분할 오류의 원인은 무엇입니까?


82

Kosaraju의 SCC (Strong Connected Component) 그래프 검색 알고리즘을 Python으로 구현하고 있습니다.

이 프로그램은 작은 데이터 세트에서 훌륭하게 실행되지만 초대형 그래프 (800,000 개 이상의 노드)에서 실행하면 "Segmentation Fault"라고 표시됩니다.

그 원인은 무엇일까요? 감사합니다!


추가 정보 : 초대형 데이터 세트에서 실행할 때 먼저 다음 오류가 발생했습니다.

"RuntimeError: maximum recursion depth exceeded in cmp"

그런 다음 사용하여 재귀 제한을 재설정합니다.

sys.setrecursionlimit(50000)

그러나 '분할 오류'가 있습니다.

무한 루프가 아니라 상대적으로 작은 데이터에서 올바르게 실행됩니다. 프로그램이 자원을 고갈시킬 수 있습니까?


10
당신이 봐 가질 수있을 수 있습니다 CrashingPython
Abhijit

2
이것은 순수 Python에서 실행 중입니까 아니면 C 확장 모듈을 사용하고 있습니까? 순수한 파이썬이라면 거기에 버그이고 축하합니다. ac 모듈을 사용하고 있다면 아마도 거기에서 segfault가 나올 것입니다.
aaronasterling

순수 파이썬입니다. 이 프로그램은 비교적 작은 데이터 세트에서 훌륭하게 실행되며 코드가 정확하다고 생각했습니다.
xiaolong

Python 문서에 따르면 :
James Thiele 2011

2
Python 문서에 따르면 :::::: 가능한 최대 제한은 플랫폼에 따라 다릅니다. 사용자는 깊은 재귀가 필요한 프로그램과 더 높은 제한을 지원하는 플랫폼이있는 경우 제한을 더 높게 설정해야 할 수 있습니다. 제한이 너무 높으면 충돌이 발생할 수 있으므로주의해서 수행해야합니다. :::::: OS를 지정하지 않았습니다. 충돌에 대한 참조는 OS의 분할 오류 를 의미 할 수 있습니다 . 더 작은 스택을 시도하십시오. 그러나 IIRC는 사용중인 알고리즘이 스택에 rntire SSC를 배치하므로 스택이 부족해질 수 있습니다.
James Thiele

답변:


80

이것은 파이썬 확장 (C로 작성)이 도달 할 수없는 메모리에 액세스하려고 할 때 발생 합니다.

다음과 같은 방법으로 추적 할 수 있습니다.

  • sys.settrace코드의 맨 처음 줄에 추가하십시오 .
  • 이 답변 에서 Markgdb설명한대로 사용 .. 명령 프롬프트에서

    gdb python
    (gdb) run /path/to/script.py
    ## wait for segfault ##
    (gdb) backtrace
    ## stack trace of the c code
    

2
고마워요,하지만 내 코드는 순수한 파이썬인데, 차이가 있습니까?
xiaolong

사용중인 Python 모듈을 확인 하시겠습니까? 일부 모듈은 파이썬으로 작성되고 다른 모듈은 C로 작성되었습니다. 버그를보고해야한다고 생각합니다.
Shiplu Mokaddim

1
유사하고 또한 도움이됩니다. stdlib의 추적 모듈은 새로운 종속성을 설치하지 않고 코드를 수정하지 않고도 스테이징 서버에서 세분화 오류의 맨 아래에 도달하는 데 도움이되었습니다.
driftcatcher 2015 년

3
OSX Sierra에서 gdb는 lldb로 대체되었습니다
kthouz


51

나는 당신이 당신의 문제를 해결했다는 것을 이해하지만,이 스레드를 읽는 다른 사람들에게는 대답이 있습니다. 당신은 당신의 운영 체제가 파이썬 프로세스에 할당하는 스택을 늘려야합니다.

이를 수행하는 방법은 운영 체제에 따라 다릅니다. Linux에서는 명령으로 ulimit -s현재 값을 확인할 수 있으며 다음과 같이 늘릴 수 있습니다.ulimit -s <new_value>

이전 값을 두 배로 늘리고 작동하지 않으면 메모리가 부족하거나 메모리가 부족할 때까지 계속 두 배로 늘리십시오.


또한 ulimit max에 도달하는지 확인하는 좋은 방법 은 모든 것을 실행 lsof하고 사용 grep하거나 wc -l추적하는 것입니다.
cdated

동의합니다. 이것은 실제로 Python 및 C ++ 구현 모두에서 segfault를 수정하여 Kosaraju의 SCC 구현에서 작동했습니다. <br/> MAC의 경우 다음을 통해 가능한 최대 값을 찾았습니다.
Rock

4
ulimit 값은 실행되는 특정 셸에 대해서만 수정되므로 실수로 전체 시스템의 값을 수정하지 않습니다
Tanmay Garg

1
나는 이것을하고 ulimit -s 16384로 끝났지 만 실행 후에도 여전히 세분화 오류가 발생했습니다.
Sreehari R

@SreehariR 더 늘리십시오. 그러나 그것은 또한 파이썬 확장 (사용중인 경우)의 문제 일 수 있습니다. (이 다른 답변) [ stackoverflow.com/a/10035594/25891] 은 디버그 방법을 제안합니다
Davide

18

세분화 오류는 일반적인 오류이며 다음과 같은 여러 원인이있을 수 있습니다.

  • 메모리 부족
  • 램 메모리 결함
  • 쿼리를 사용하여 db에서 거대한 데이터 세트 가져 오기 (인출 된 데이터의 크기가 스왑 메모리보다 큰 경우)
  • 잘못된 쿼리 / 버그 코드
  • 긴 루프 (다중 재귀)

2

ulimit 업데이트는 Python (Python segfault .. who know!) 및 C ++ 구현 모두에서 segfault를 수정하여 Kosaraju의 SCC 구현에 적용되었습니다.

내 MAC의 경우 다음을 통해 가능한 최대 값을 찾았습니다.

$ ulimit -s -H
65532

그 값을 업데이트하는 방법? 그 값은 어떤 유형의 단위입니까?
Pablo

2

Google 검색에서이 기사를 찾았지만 다음 "개인 솔루션"에 대해 논의 된 내용을 보지 못했습니다.


Linux 용 Windows 하위 시스템에서 Python 3.7에 대한 최근의 성가심은 동일한 Pandas 라이브러리가있는 두 대의 컴퓨터에서 하나는 저에게 segmentation fault, 다른 하나는 경고를보고 한다는 것 입니다. 어떤 것이 더 새로운 것인지 확실하지 않지만 "다시 설치" pandas하면 문제가 해결됩니다.

내가 버기 머신에서 실행 한 명령.

conda install pandas

자세한 내용 : 동일한 스크립트 (Git를 통해 동기화 됨)를 실행하고 있었고 둘 다 WSL + Anaconda를 사용하는 Windows 10 컴퓨터입니다. 여기에 케이스를 만드는 스크린 샷이 있습니다. 또한 명령 줄 python이에 대해 불평 하는 컴퓨터에서 Segmentation fault (core dumped)Jupyter lab은 매번 커널을 다시 시작합니다. 더 나쁜 것은 전혀 경고가 주어지지 않았다는 것입니다.

여기에 이미지 설명 입력


몇 달 후 업데이트 : Windows 시스템에서 Jupyter 서버 호스팅을 중단했습니다. 이제 Windows에서 WSL을 사용하여 Linux 서버에서 열린 원격 포트를 가져오고 원격 Linux 컴퓨터에서 모든 작업을 실행합니다. 몇 달 동안 실행 오류가 발생하지 않았습니다. :)


0

RPI에서 dlib를 업그레이드 한 후이 세분화 오류가 발생했습니다. 위의 Shiplu Mokaddim이 제안한 스택을 추적하고 OpenBLAS 라이브러리에 정착했습니다.

OpenBLAS도 다중 스레드이기 때문에 muilt 스레드 응용 프로그램에서 OpenBLAS를 사용하면 세그먼트 오류가 발생할 때까지 스레드가 기하 급수적으로 증가합니다. 다중 스레드 응용 프로그램의 경우 OpenBlas를 단일 스레드 모드로 설정합니다.

Python 가상 환경에서 OpenBLAS에 다음을 편집하여 단일 스레드 만 사용하도록 지시합니다.

    $ workon <myenv>
    $ nano .virtualenv/<myenv>/bin/postactivate

다음을 추가하십시오.

    export OPENBLAS_NUM_THREADS=1 
    export OPENBLAS_MAIN_FREE=1

재부팅 후 이전에 충돌이 발생했던 rpi3b에서 모든 이미지 인식 앱을 실행할 수있었습니다.

참조 : https://github.com/ageitgey/face_recognition/issues/294


-1

스택 메모리가 부족한 것 같습니다. Davide가 말한 것처럼 그것을 늘릴 수 있습니다. 파이썬 코드에서 수행하려면 스레딩을 사용하여 "main ()"을 실행해야합니다.

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()

출처 : c1729 's post on codeforces . PyPy로 실행하는 것은 약간 까다 롭습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.