2013-02-16 54 views
31

Tôi có một kịch bản rất đơn giản bằng Python, nhưng đối với một số lý do tôi nhận được lỗi sau khi chạy một lượng lớn dữ liệu:Python đôi lỗi miễn phí cho các tập dữ liệu khổng lồ

*** glibc detected *** python: double free or corruption (out): 0x00002af5a00cc010 *** 

tôi đã quen với các lỗi này đến trong C hoặc C++, khi một người cố gắng giải phóng bộ nhớ đã được giải phóng. Tuy nhiên, bởi sự hiểu biết của tôi về Python (và đặc biệt là cách tôi đã viết mã), tôi thực sự không hiểu tại sao điều này sẽ xảy ra.

Đây là mã:

#!/usr/bin/python -tt                                                       

import sys, commands, string 
import numpy as np 
import scipy.io as io 
from time import clock 

W = io.loadmat(sys.argv[1])['W'] 
size = W.shape[0] 
numlabels = int(sys.argv[2]) 
Q = np.zeros((size, numlabels), dtype=np.double) 
P = np.zeros((size, numlabels), dtype=np.double) 
Q += 1.0/Q.shape[1] 
nu = 0.001 
mu = 0.01 
start = clock() 
mat = -nu + mu*(W*(np.log(Q)-1)) 
end = clock() 
print >> sys.stderr, "Time taken to compute matrix: %.2f seconds"%(end-start) 

Người ta có thể hỏi, tại sao khai báo một P và một mảng Q NumPy? Tôi chỉ đơn giản làm điều đó để phản ánh các điều kiện thực tế (vì mã này chỉ đơn giản là một phân đoạn của những gì tôi thực sự làm, nơi tôi cần một ma trận P và khai báo nó trước).

Tôi có quyền truy cập vào máy 192GB và vì vậy tôi đã thử nghiệm điều này trên một ma trận thưa thớt SciPy rất lớn (2,2 triệu 2,2 triệu, nhưng rất thưa thớt, đó không phải là vấn đề). Bộ nhớ chính được lấy bởi các ma trận Q, P và mat, vì chúng đều là 2,2 triệu 2000 ma trận (kích thước = 2,2 triệu, numlabels = 2000). Bộ nhớ cao nhất lên đến 131GB, phù hợp với bộ nhớ. Trong khi ma trận mat đang được tính toán, tôi nhận được lỗi glibc, và quá trình của tôi tự động đi vào trạng thái ngủ (S), mà không cần deallocating 131GB nó đã đưa lên.

Với lỗi kỳ lạ (đối với Python) (Tôi không giải thích rõ ràng), và thực tế là nó hoạt động tốt cho các kích thước ma trận nhỏ hơn (khoảng 1,5 triệu vào năm 2000), tôi thực sự không chắc chắn nơi bắt đầu gỡ lỗi điều này.

Là điểm bắt đầu, tôi đã đặt "ulimit -s unlimited" trước khi chạy nhưng không có kết quả.

Bất kỳ trợ giúp hoặc thông tin chi tiết nào về hành vi của kẻ thù với số lượng dữ liệu thực sự lớn sẽ được hoan nghênh.

Lưu ý rằng đây KHÔNG phải là lỗi hết bộ nhớ - tôi có 196GB và quy trình của tôi đạt khoảng 131GB và vẫn ở đó một thời gian trước khi đưa ra lỗi bên dưới.

Cập nhật: 16 tháng hai 2013 (13:10 PST):

Theo gợi ý, tôi chạy Python với GDB. Điều thú vị là, trên một GDB chạy Tôi quên để thiết lập các giới hạn kích thước ngăn xếp để "không giới hạn", và nhận được kết quả như sau:

*** glibc detected *** /usr/bin/python: munmap_chunk(): invalid pointer: 0x00007fe7508a9010 *** 
======= Backtrace: ========= 
/lib64/libc.so.6(+0x733b6)[0x7ffff6ec23b6] 
/usr/lib64/python2.7/site-packages/numpy/core/multiarray.so(+0x4a496)[0x7ffff69fc496] 
/usr/lib64/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x4e67)[0x7ffff7af48c7] 
/usr/lib64/libpython2.7.so.1.0(PyEval_EvalCodeEx+0x309)[0x7ffff7af6c49] 
/usr/lib64/libpython2.7.so.1.0(PyEval_EvalCode+0x32)[0x7ffff7b25592] 
/usr/lib64/libpython2.7.so.1.0(+0xfcc61)[0x7ffff7b33c61] 
/usr/lib64/libpython2.7.so.1.0(PyRun_FileExFlags+0x84)[0x7ffff7b34074] 
/usr/lib64/libpython2.7.so.1.0(PyRun_SimpleFileExFlags+0x189)[0x7ffff7b347c9] 
/usr/lib64/libpython2.7.so.1.0(Py_Main+0x36c)[0x7ffff7b3e1bc] 
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7ffff6e6dbfd] 
/usr/bin/python[0x4006e9] 
======= Memory map: ======== 
00400000-00401000 r-xp 00000000 09:01 50336181       /usr/bin/python2.7 
00600000-00601000 r--p 00000000 09:01 50336181       /usr/bin/python2.7 
00601000-00602000 rw-p 00001000 09:01 50336181       /usr/bin/python2.7 
00602000-00e5f000 rw-p 00000000 00:00 0         [heap] 
7fdf2584c000-7ffff0a66000 rw-p 00000000 00:00 0 
7ffff0a66000-7ffff0a6b000 r-xp 00000000 09:01 50333916     /usr/lib64/python2.7/lib-dynload/mmap.so 
7ffff0a6b000-7ffff0c6a000 ---p 00005000 09:01 50333916     /usr/lib64/python2.7/lib-dynload/mmap.so 
7ffff0c6a000-7ffff0c6b000 r--p 00004000 09:01 50333916     /usr/lib64/python2.7/lib-dynload/mmap.so 
7ffff0c6b000-7ffff0c6c000 rw-p 00005000 09:01 50333916     /usr/lib64/python2.7/lib-dynload/mmap.so 
7ffff0c6c000-7ffff0c77000 r-xp 00000000 00:12 54138483     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/streams.so 
7ffff0c77000-7ffff0e76000 ---p 0000b000 00:12 54138483     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/streams.so 
7ffff0e76000-7ffff0e77000 r--p 0000a000 00:12 54138483     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/streams.so 
7ffff0e77000-7ffff0e78000 rw-p 0000b000 00:12 54138483     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/streams.so 
7ffff0e78000-7ffff0e79000 rw-p 00000000 00:00 0 
7ffff0e79000-7ffff0e9b000 r-xp 00000000 00:12 54138481     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio5_utils.so 
7ffff0e9b000-7ffff109a000 ---p 00022000 00:12 54138481     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio5_utils.so 
7ffff109a000-7ffff109b000 r--p 00021000 00:12 54138481     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio5_utils.so 
7ffff109b000-7ffff109f000 rw-p 00022000 00:12 54138481     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio5_utils.so 
7ffff109f000-7ffff10a0000 rw-p 00000000 00:00 0 
7ffff10a0000-7ffff10a5000 r-xp 00000000 09:01 50333895     /usr/lib64/python2.7/lib-dynload/zlib.so 
7ffff10a5000-7ffff12a4000 ---p 00005000 09:01 50333895     /usr/lib64/python2.7/lib-dynload/zlib.so 
7ffff12a4000-7ffff12a5000 r--p 00004000 09:01 50333895     /usr/lib64/python2.7/lib-dynload/zlib.so 
7ffff12a5000-7ffff12a7000 rw-p 00005000 09:01 50333895     /usr/lib64/python2.7/lib-dynload/zlib.so 
7ffff12a7000-7ffff12ad000 r-xp 00000000 00:12 54138491     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio_utils.so 
7ffff12ad000-7ffff14ac000 ---p 00006000 00:12 54138491     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio_utils.so 
7ffff14ac000-7ffff14ad000 r--p 00005000 00:12 54138491     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio_utils.so 
7ffff14ad000-7ffff14ae000 rw-p 00006000 00:12 54138491     /home/avneesh/.local/lib/python2.7/site-packages/scipy/io/matlab/mio_utils.so 
7ffff14ae000-7ffff14b5000 r-xp 00000000 00:12 54138562     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_csgraph.so 
7ffff14b5000-7ffff16b4000 ---p 00007000 00:12 54138562     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_csgraph.so 
7ffff16b4000-7ffff16b5000 r--p 00006000 00:12 54138562     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_csgraph.so 
7ffff16b5000-7ffff16b6000 rw-p 00007000 00:12 54138562     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_csgraph.so 
7ffff16b6000-7ffff17c2000 r-xp 00000000 00:12 54138558     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_bsr.so 
7ffff17c2000-7ffff19c2000 ---p 0010c000 00:12 54138558     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_bsr.so 
7ffff19c2000-7ffff19c3000 r--p 0010c000 00:12 54138558     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_bsr.so 
7ffff19c3000-7ffff19c6000 rw-p 0010d000 00:12 54138558     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_bsr.so 
7ffff19c6000-7ffff19d5000 r-xp 00000000 00:12 54138561     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_dia.so 
7ffff19d5000-7ffff1bd4000 ---p 0000f000 00:12 54138561     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_dia.so 
7ffff1bd4000-7ffff1bd5000 r--p 0000e000 00:12 54138561     /home/avneesh/.local/lib/python2.7/site-packages/scipy/sparse/sparsetools/_dia.so 
Program received signal SIGABRT, Aborted. 
0x00007ffff6e81ab5 in raise() from /lib64/libc.so.6 
(gdb) bt 
#0 0x00007ffff6e81ab5 in raise() from /lib64/libc.so.6 
#1 0x00007ffff6e82fb6 in abort() from /lib64/libc.so.6 
#2 0x00007ffff6ebcdd3 in __libc_message() from /lib64/libc.so.6 
#3 0x00007ffff6ec23b6 in malloc_printerr() from /lib64/libc.so.6 
#4 0x00007ffff69fc496 in ??() from /usr/lib64/python2.7/site-packages/numpy/core/multiarray.so 
#5 0x00007ffff7af48c7 in PyEval_EvalFrameEx() from /usr/lib64/libpython2.7.so.1.0 
#6 0x00007ffff7af6c49 in PyEval_EvalCodeEx() from /usr/lib64/libpython2.7.so.1.0 
#7 0x00007ffff7b25592 in PyEval_EvalCode() from /usr/lib64/libpython2.7.so.1.0 
#8 0x00007ffff7b33c61 in ??() from /usr/lib64/libpython2.7.so.1.0 
#9 0x00007ffff7b34074 in PyRun_FileExFlags() from /usr/lib64/libpython2.7.so.1.0 
#10 0x00007ffff7b347c9 in PyRun_SimpleFileExFlags() from /usr/lib64/libpython2.7.so.1.0 
#11 0x00007ffff7b3e1bc in Py_Main() from /usr/lib64/libpython2.7.so.1.0 
#12 0x00007ffff6e6dbfd in __libc_start_main() from /lib64/libc.so.6 
#13 0x00000000004006e9 in _start() 

Khi tôi đặt giới hạn ngăn xếp kích thước không giới hạn", tôi nhận được như sau:

*** glibc detected *** /usr/bin/python: double free or corruption (out): 0x00002abb2732c010 *** 
^X^C 
Program received signal SIGINT, Interrupt. 
0x00002aaaab9d08fe in __lll_lock_wait_private() from /lib64/libc.so.6 
(gdb) bt 
#0 0x00002aaaab9d08fe in __lll_lock_wait_private() from /lib64/libc.so.6 
#1 0x00002aaaab969f2e in _L_lock_9927() from /lib64/libc.so.6 
#2 0x00002aaaab9682d1 in free() from /lib64/libc.so.6 
#3 0x00002aaaaaabbfe2 in _dl_scope_free() from /lib64/ld-linux-x86-64.so.2 
#4 0x00002aaaaaab70a4 in _dl_map_object_deps() from /lib64/ld-linux-x86-64.so.2 
#5 0x00002aaaaaabcaa0 in dl_open_worker() from /lib64/ld-linux-x86-64.so.2 
#6 0x00002aaaaaab85f6 in _dl_catch_error() from /lib64/ld-linux-x86-64.so.2 
#7 0x00002aaaaaabc5da in _dl_open() from /lib64/ld-linux-x86-64.so.2 
#8 0x00002aaaab9fb530 in do_dlopen() from /lib64/libc.so.6 
#9 0x00002aaaaaab85f6 in _dl_catch_error() from /lib64/ld-linux-x86-64.so.2 
#10 0x00002aaaab9fb5cf in dlerror_run() from /lib64/libc.so.6 
#11 0x00002aaaab9fb637 in __libc_dlopen_mode() from /lib64/libc.so.6 
#12 0x00002aaaab9d60c5 in init() from /lib64/libc.so.6 
#13 0x00002aaaab080933 in pthread_once() from /lib64/libpthread.so.0 
#14 0x00002aaaab9d61bc in backtrace() from /lib64/libc.so.6 
#15 0x00002aaaab95dde7 in __libc_message() from /lib64/libc.so.6 
#16 0x00002aaaab9633b6 in malloc_printerr() from /lib64/libc.so.6 
#17 0x00002aaaab9682dc in free() from /lib64/libc.so.6 
#18 0x00002aaaabef1496 in ??() from /usr/lib64/python2.7/site-packages/numpy/core/multiarray.so 
#19 0x00002aaaaad888c7 in PyEval_EvalFrameEx() from /usr/lib64/libpython2.7.so.1.0 
#20 0x00002aaaaad8ac49 in PyEval_EvalCodeEx() from /usr/lib64/libpython2.7.so.1.0 
#21 0x00002aaaaadb9592 in PyEval_EvalCode() from /usr/lib64/libpython2.7.so.1.0 
#22 0x00002aaaaadc7c61 in ??() from /usr/lib64/libpython2.7.so.1.0 
#23 0x00002aaaaadc8074 in PyRun_FileExFlags() from /usr/lib64/libpython2.7.so.1.0 
#24 0x00002aaaaadc87c9 in PyRun_SimpleFileExFlags() from /usr/lib64/libpython2.7.so.1.0 
#25 0x00002aaaaadd21bc in Py_Main() from /usr/lib64/libpython2.7.so.1.0 
#26 0x00002aaaab90ebfd in __libc_start_main() from /lib64/libc.so.6 
#27 0x00000000004006e9 in _start() 

Điều này làm cho tôi tin rằng vấn đề cơ bản là với mô-đun lõi đa lõi cứng (dòng # 4 trong đầu ra đầu tiên và dòng # 18 trong phần thứ hai) .Tôi sẽ đưa nó lên dưới dạng báo cáo lỗi trong cả hai loại gọn gàng và scipy chỉ trong trường hợp.

Có ai nhìn thấy điều này trước đây không?

Cập nhật: ngày 17 tháng 2 năm 2013 (16:45 PST)

Tôi tìm thấy một máy tính mà tôi có thể chạy mã trên đó có một phiên bản mới hơn của scipy (0.11) và NumPy (1.7. 0). Chạy mã thẳng lên (không có GDB) dẫn đến lỗi seg mà không có bất kỳ đầu ra nào để stdout hoặc stderr.Chạy lại thông qua GDB, tôi nhận được những điều sau đây:

Program received signal SIGSEGV, Segmentation fault. 
0x00002aaaabead970 in ??() from /lib/x86_64-linux-gnu/libc.so.6 
(gdb) bt 
#0 0x00002aaaabead970 in ??() from /lib/x86_64-linux-gnu/libc.so.6 
#1 0x00002aaaac5fcd04 in PyDataMem_FREE (ptr=<optimized out>, $K8=<optimized out>) at numpy/core/src/multiarray/multiarraymodule.c:3510 
#2 array_dealloc (self=0xc00ab7edbfc228fe) at numpy/core/src/multiarray/arrayobject.c:416 
#3 0x0000000000498eac in PyEval_EvalFrameEx() 
#4 0x000000000049f1c0 in PyEval_EvalCodeEx() 
#5 0x00000000004a9081 in PyRun_FileExFlags() 
#6 0x00000000004a9311 in PyRun_SimpleFileExFlags() 
#7 0x00000000004aa8bd in Py_Main() 
#8 0x00002aaaabe4f76d in __libc_start_main() from /lib/x86_64-linux-gnu/libc.so.6 
#9 0x000000000041b9b1 in _start() 

Tôi hiểu điều này không hữu ích như NumPy được biên dịch với biểu tượng gỡ lỗi, tôi sẽ cố gắng thực hiện điều đó và đăng đầu ra sau.

+4

Thú vị - Mặc dù, bạn có thể tốt hơn khi gửi báo cáo lỗi với 'scipy'. Có lẽ biên dịch với '-g' và chạy dưới' gdb' cũng sẽ hữu ích - Ít nhất thì bạn có thể thấy mã ở đâu khi lỗi xảy ra ... – mgilson

+0

bạn đang sử dụng hệ điều hành nào? (và dữ liệu này là gì?) – tacaswell

+3

Bạn đang sử dụng phiên bản Python/numpy nào? Tôi thấy một số báo cáo lỗi về điều này, nhưng chúng đã cũ và cho thấy sự cố đã được khắc phục. – BrenBarn

Trả lời

5

Sau khi thảo luận về cùng một vấn đề trên trang Numpy Github (https://github.com/numpy/numpy/issues/2995), tôi đã chú ý rằng Numpy/Scipy sẽ không hỗ trợ một số lượng lớn các số không trong ma trận thưa thớt kết quả.

Về cơ bản, W là ma trận thưa thớt và Q (hoặc np.log(Q)-1) là một ma trận dày đặc. Khi nhân một ma trận dày đặc với một ma trận thưa thớt, sản phẩm thu được cũng sẽ được biểu diễn dưới dạng ma trận thưa thớt (điều này tạo ra rất nhiều ý nghĩa). Tuy nhiên, lưu ý rằng vì tôi không có hàng nào trong ma trận W của mình, sản phẩm kết quả W*(np.log(Q)-1) sẽ có nnz > 2^31 (2,2 triệu nhân với 2000) và điều này vượt quá số phần tử tối đa trong ma trận thưa thớt trong các phiên bản hiện tại của Scipy.

Ở giai đoạn này, tôi không chắc chắn cách khác để làm việc này, chặn việc triển khai lại bằng ngôn ngữ khác. Có lẽ nó vẫn có thể được thực hiện bằng Python, nhưng nó có thể tốt hơn nếu chỉ viết một bản C++ và Eigen.

Một lời cảm ơn đặc biệt đến pv. để giúp đỡ về điều này để xác định chính xác vấn đề và cảm ơn tất cả mọi người khác vì động não!

+0

Dường như với tôi rằng nếu nó hợp lý để bạn có một ma trận dày đặc lớn như 'W * (np.log (Q) -1)', nó có thể tốt _also_ là hợp lý để bạn có một ma trận dày đặc lớn như 'W'. Trong trường hợp đó, có một câu trả lời dễ dàng: 'W.todense() * (np.log (Q) -1)'. – abarnert

+0

Không, tôi không nói đó là sự thật. '' 'W * (np.log (Q) -1)' '' là '' '2,2 triệu x 2000''' và' '' W.todense() '' 'là' 2,2 triệu x 2,2 triệu' ''. – Avneesh

1

Về cơ bản, W là một ma trận thưa thớt, và Q (hoặc np.log(Q)-1) là một ma trận dày đặc. Khi nhân một ma trận dày đặc với một ma trận thưa thớt, sản phẩm thu được cũng sẽ được biểu diễn dưới dạng ma trận thưa thớt (điều này tạo ra rất nhiều ý nghĩa).

Tôi có thể bị thiếu một cái gì đó thực sự rõ ràng ở đây, và sẽ kết thúc lên trông như một thằng ngốc, nhưng ...

Nếu Q là một ma trận dày đặc, và bạn đang hy vọng để lưu trữ kết quả như một dày đặc ma trận, bạn có thể có đủ để giữ W như là một ma trận dày đặc là tốt. Điều này có nghĩa là:

W.todense()*(np.log(Q)-1) 

Xem chi tiết, như bạn đã tính trong nhận xét, điều này sẽ yêu cầu bộ nhớ tạm thời 35,8 GB. Cho rằng bạn đã có 131GB dữ liệu và điều này "phù hợp thoải mái vào bộ nhớ", có vẻ như ít nhất là tạm thời sử dụng 35,8 GB khác sẽ là hợp lý.

Nếu đó là không phải hợp lý, bạn luôn có thể tự phân hủy phép nhân ma trận. Rõ ràng là thực hiện nó theo hàng hoặc cột theo cột sẽ làm cho toàn bộ quá trình của bạn chậm hơn nhiều (có thể không nhiều như đẩy quá trình trên các cạnh vào trao đổi, nhưng vẫn có thể quá chậm để được chấp nhận). Nhưng thực hiện nó, ví dụ, một đoạn giá trị 1GB hàng tại một thời điểm không nên quá tệ. Điều đó có nghĩa là lưu trữ tạm thời theo thứ tự của một vài GB, và có lẽ chỉ là một sự chậm lại nhỏ. Tất nhiên nó phức tạp hơn và xấu mã, nhưng không phải là không thể quản lý như vậy.

+0

Tôi không nghĩ những gì bạn đã nói ra. '' 'W''' là một ma trận' '' N * N''', trong đó '' 'N''' là 2,2 triệu, không phải là ma trận' '' N * M''' và '' 'Q '' 'là một ma trận' '' N * M''', trong đó '' 'M = 2000'''. Chuyển đổi ma trận thưa thớt, hiện có 42,666,354 số không 0 (và do đó tổng bộ nhớ = '' '(42666354 * 8)/(2^20) = ~ 326MB'''), thành một ma trận dày đặc có nghĩa là' '' (2,2 triệu * 2,2 triệu * 8)/(2^30) ~ 35,8 GB'''. Điều này làm tăng đáng kể bộ nhớ. – Avneesh

+0

Ngoài ra, kế hoạch ban đầu là để quy mô này lên đến '' 'N = 7,2 triệu''', mà sẽ làm cho' '' W.todense() '' 'giải pháp ít khả thi hơn. – Avneesh

+0

@Avneesh: Tôi nhận ra nó có nghĩa là bộ nhớ nhiều hơn, nhưng giả định của tôi là nếu 131GB "phù hợp thoải mái vào bộ nhớ", thì 35.8GB lưu trữ tạm thời khác (trong thời gian nhân này) có thể chấp nhận được. Tất nhiên nó có thể _not_ được chấp nhận, nhưng nó có vẻ như nó đã được ít nhất là cố gắng. – abarnert

Các vấn đề liên quan