Nguyên nhân gây ra lỗi phân đoạn Python?


82

Tôi đang triển khai thuật toán tìm kiếm đồ thị Thành phần được kết nối mạnh (SCC) của Kosaraju bằng Python.

Chương trình chạy tuyệt vời trên tập dữ liệu nhỏ, nhưng khi tôi chạy nó trên một đồ thị siêu lớn (hơn 800.000 nút), nó cho biết "Lỗi phân đoạn".

Điều gì có thể là nguyên nhân của nó? Cảm ơn bạn!


Thông tin bổ sung: Đầu tiên, tôi gặp lỗi này khi chạy trên tập dữ liệu siêu lớn:

"RuntimeError: maximum recursion depth exceeded in cmp"

Sau đó, tôi đặt lại giới hạn đệ quy bằng cách sử dụng

sys.setrecursionlimit(50000)

nhưng có 'lỗi phân đoạn'

Hãy tin tôi rằng nó không phải là một vòng lặp vô hạn, nó chạy chính xác trên dữ liệu tương đối nhỏ hơn. Có thể chương trình đã cạn kiệt tài nguyên?


10
Có thể bạn có thể có một cái nhìn CrashingPython
Abhijit

2
Điều này đang chạy bằng Python thuần túy hay bạn đang sử dụng mô-đun mở rộng C? Nếu đó là Python thuần túy thì đó là một lỗi ở đó và xin chúc mừng. Nếu bạn đang sử dụng mô-đun ac, thì segfault có thể đến từ đó.
aaronasterling

đó là Trăn tinh. Chương trình chạy tuyệt vời trên tập dữ liệu tương đối nhỏ và nó khiến tôi nghĩ rằng mã là chính xác.
xiaolong

Theo tài liệu Python:
James Thiele

2
Theo tài liệu Python :::::: Giới hạn cao nhất có thể là phụ thuộc vào nền tảng. Người dùng có thể cần đặt giới hạn cao hơn khi họ có chương trình yêu cầu đệ quy sâu và nền tảng hỗ trợ giới hạn cao hơn. Điều này nên được thực hiện cẩn thận, vì giới hạn quá cao có thể dẫn đến sự cố. :::::: Bạn không chỉ định hệ điều hành. Tham chiếu đến sự cố có thể có nghĩa là lỗi phân đoạn trên hệ điều hành của bạn. Hãy thử một ngăn xếp nhỏ hơn. Nhưng thuật toán IIRC bạn đang sử dụng đặt rntire SSC trên ngăn xếp nên bạn có thể hết ngăn xếp.
James Thiele

Câu trả lời:


80

Điều này xảy ra khi một tiện ích mở rộng python (được viết bằng C) cố gắng truy cập vào một bộ nhớ ngoài tầm với.

Bạn có thể theo dõi nó theo những cách sau.

  • Thêm sys.settracevào dòng đầu tiên của mã.
  • Sử dụng gdbnhư được mô tả bởi Đánh dấu trong câu trả lời này .. Tại dấu nhắc lệnh

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

2
cảm ơn, nhưng mã của tôi là python thuần túy, nó có tạo ra sự khác biệt không?
xiaolong

Kiểm tra mô-đun python nào bạn đang sử dụng? Một số mô-đun được viết bằng python và các mô-đun khác bằng C. Tôi nghĩ bạn cần báo cáo lỗi.
Shiplu Mokaddim

1
tương tự, cũng hữu ích: mô-đun theo dõi của stdlib vừa giúp tôi giải quyết tận cùng lỗi phân đoạn trên máy chủ dàn, mà không cần cài đặt phụ thuộc mới và không sửa đổi mã.
driftcatcher

3
trên OSX Sierra, gdb đã được thay thế bởi LLĐB
kthouz


51

Tôi hiểu rằng bạn đã giải quyết được sự cố của mình, nhưng đối với những người khác đang đọc chuỗi này, đây là câu trả lời: bạn phải tăng ngăn xếp mà hệ điều hành của bạn phân bổ cho quy trình python.

Cách thực hiện, phụ thuộc vào hệ điều hành. Trong linux, bạn có thể kiểm tra bằng lệnh ulimit -sgiá trị hiện tại của mình và bạn có thể tăng giá trị đó bằngulimit -s <new_value>

Hãy thử nhân đôi giá trị trước đó và tiếp tục nhân đôi nếu nó không hoạt động, cho đến khi bạn tìm thấy giá trị đó hoặc hết bộ nhớ.


Ngoài ra, một cách tốt để kiểm tra xem bạn có sắp đạt được mức ulimit max hay không là chạy lsofvà sử dụng grephoặc wc -ltheo dõi mọi thứ.
cdated vào

Tôi đồng tình. Điều này thực sự đã hoạt động cho việc triển khai SCC của Kosaraju của tôi bằng cách sửa lỗi segfault trên cả triển khai Python và C ++. <br/> Đối với MAC của tôi, tôi đã tìm ra mức tối đa có thể qua:
Rock

4
lưu ý rằng giá trị ulimit được sửa đổi chỉ dành cho các lớp vỏ đặc biệt nó được thực hiện trong, do đó bạn không vô tình thay đổi giá trị cho toàn bộ hệ thống của bạn
Tanmay Garg

1
Tôi đã làm điều này và kết thúc với ulimit -s 16384, tuy nhiên sau khi chạy tôi vẫn gặp lỗi phân đoạn.
Sreehari R

@SreehariR Hãy thử tăng nó nhiều hơn nữa. Tuy nhiên nó cũng có thể là một vấn đề với một phần mở rộng python (nếu bạn đang sử dụng bất kỳ), trong đó (câu trả lời này khác) [ stackoverflow.com/a/10035594/25891] cho thấy làm thế nào để gỡ lỗi
Davide

18

Lỗi phân đoạn là một lỗi chung, có nhiều lý do có thể xảy ra:

  • Bộ nhớ thấp
  • Bộ nhớ Ram bị lỗi
  • Tìm nạp một tập dữ liệu khổng lồ từ db bằng cách sử dụng truy vấn (nếu kích thước của dữ liệu được tìm nạp lớn hơn trao đổi mem)
  • truy vấn sai / mã lỗi
  • có vòng lặp dài (nhiều đệ quy)

2

Cập nhật ulimit đã hoạt động cho việc triển khai SCC của Kosaraju của tôi bằng cách sửa lỗi segfault trên cả triển khai Python (Python segfault .. ai biết!) Và C ++.

Đối với MAC của tôi, tôi đã tìm ra mức tối đa có thể thông qua:

$ ulimit -s -H
65532

làm thế nào để cập nhật giá trị đó? giá trị đó ở loại đơn vị nào?
Pablo

2

Google tìm kiếm cho tôi bài viết này và tôi không thấy "giải pháp cá nhân" sau đây được thảo luận.


Điều khó chịu gần đây của tôi với Python 3.7 trên Hệ thống con Windows dành cho Linux là: trên hai máy có cùng thư viện Pandas, một máy báo cho tôi segmentation faultvà máy còn lại cảnh báo. Không rõ cái nào mới hơn, nhưng "đang cài đặt lại"pandas giải quyết được vấn đề.

Lệnh mà tôi đã chạy trên máy có lỗi.

conda install pandas

Thông tin chi tiết: Tôi đang chạy các tập lệnh giống hệt nhau (được đồng bộ hóa thông qua Git) và cả hai đều là máy Windows 10 với WSL + Anaconda. Đây là ảnh chụp màn hình để làm cho trường hợp. Ngoài ra, trên máy mà dòng lệnh pythonsẽ bị phàn nàn Segmentation fault (core dumped), phòng thí nghiệm Jupyter chỉ cần khởi động lại hạt nhân mỗi lần. Tệ hơn nữa, không có cảnh báo nào được đưa ra.

nhập mô tả hình ảnh ở đây


Cập nhật vài tháng sau: Tôi đã bỏ lưu trữ máy chủ Jupyter trên máy Windows. Bây giờ tôi sử dụng WSL trên Windows để tìm nạp các cổng từ xa được mở trên máy chủ Linux và chạy tất cả các công việc của tôi trên máy Linux từ xa. Tôi chưa bao giờ gặp bất kỳ lỗi thực thi nào trong nhiều tháng :)


0

Tôi gặp phải lỗi phân đoạn này sau khi nâng cấp dlib trên RPI. Tôi đã theo dõi lại ngăn xếp theo đề xuất của Shiplu Mokaddim ở trên và nó đã giải quyết trên thư viện OpenBLAS.

Vì OpenBLAS cũng đa luồng, việc sử dụng nó trong một ứng dụng phân luồng sẽ nhân các luồng theo cấp số nhân cho đến khi lỗi phân đoạn. Đối với các ứng dụng đa luồng, hãy đặt OpenBlas thành chế độ luồng đơn.

Trong môi trường ảo python, yêu cầu OpenBLAS chỉ sử dụng một luồng duy nhất bằng cách chỉnh sửa:

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

và thêm:

    export OPENBLAS_NUM_THREADS=1 
    export OPENBLAS_MAIN_FREE=1

Sau khi khởi động lại, tôi đã có thể chạy tất cả các ứng dụng nhận dạng hình ảnh của mình trên rpi3b mà trước đó nó đã bị lỗi.

tham khảo: https://github.com/ageitgey/face_recognition/issues/294


-1

Có vẻ như bạn đã hết bộ nhớ ngăn xếp. Bạn có thể muốn tăng nó như Davide đã nêu. Để làm điều đó trong mã python, bạn sẽ cần chạy "main ()" của mình bằng cách sử dụng luồng:

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

Nguồn: bài đăng của c1729 trên codeforces . Chạy nó bằng PyPy phức tạp hơn một chút .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.