2013-05-29 35 views
15

Tôi đang sử dụng hàm numpy.array() để tạo các lệnh ndd từ numpy.float64 từ danh sách.Tại sao numpy.array() đôi khi rất chậm?

Tôi nhận thấy rằng điều này rất chậm khi danh sách chứa Không có hoặc danh sách danh sách được cung cấp.

Dưới đây là một số ví dụ với thời gian. Có cách giải quyết rõ ràng nhưng tại sao điều này quá chậm?

Ví dụ về danh sách các None:

### Very slow to call array() with list of None 
In [3]: %timeit numpy.array([None]*100000, dtype=numpy.float64) 
1 loops, best of 3: 240 ms per loop 

### Problem doesn't exist with array of zeroes 
In [4]: %timeit numpy.array([0.0]*100000, dtype=numpy.float64) 
100 loops, best of 3: 9.94 ms per loop 

### Also fast if we use dtype=object and convert to float64 
In [5]: %timeit numpy.array([None]*100000, dtype=numpy.object).astype(numpy.float64) 
100 loops, best of 3: 4.92 ms per loop 

### Also fast if we use fromiter() insead of array() 
In [6]: %timeit numpy.fromiter([None]*100000, dtype=numpy.float64) 
100 loops, best of 3: 3.29 ms per loop 

Ví dụ về danh sách liệt kê:

### Very slow to create column matrix 
In [7]: %timeit numpy.array([[0.0]]*100000, dtype=numpy.float64) 
1 loops, best of 3: 353 ms per loop 

### No problem to create column vector and reshape 
In [8]: %timeit numpy.array([0.0]*100000, dtype=numpy.float64).reshape((-1,1)) 
100 loops, best of 3: 10 ms per loop 

### Can use itertools to flatten input lists 
In [9]: %timeit numpy.fromiter(itertools.chain.from_iterable([[0.0]]*100000),dtype=numpy.float64).reshape((-1,1)) 
100 loops, best of 3: 9.65 ms per loop 
+7

để tạo ra một mảng trống rỗng, sử dụng 'a = numpy.empty (100000)'. Để tạo một mảng với tất cả các số không: 'a = numpy.zeros (100000)'. – jfs

+0

Mục tiêu của tôi không phải là tạo ra một mảng số không hoặc rỗng, nhưng tôi đang gặp sự cố về hiệu suất khi Không có trong tập dữ liệu. Nếu tôi tạo mảng và đầu tiên và thiết lập các giá trị tôi có khá nhiều vấn đề tương tự. Trong [18]: a = numpy.empty ((100000,)) Trong [19]:% timeit a [:] = [None] * 100000 1 vòng, tốt nhất là 3: 209 ms mỗi vòng Trong [20]:% timeit a [:] = [0] * 100000 100 vòng, tốt nhất là 3: 9,59 ms mỗi vòng – MarkW

+0

thực sự nó là một câu hỏi thú vị: tại sao '[3]' chậm hơn nhiều so với '[5 ] '(nó có thể là một lỗi hoặc chỉ là một trường hợp sử dụng hiếm hoi không được tối ưu hóa). Để lặp lại 'NaN', hãy gọi' numpy.repeat (float ("nan"), 100000) ' – jfs

Trả lời

1

tôi đoán sẽ là mã để chuyển đổi danh sách chỉ gọi float trên tất cả mọi thứ. Nếu đối số xác định __float__, chúng tôi gọi đó là, nếu không chúng tôi coi nó như một chuỗi (ném một ngoại lệ vào Không, chúng tôi bắt và đặt trong np.nan). Việc xử lý ngoại lệ nên tương đối chậm hơn.

Thời gian dường như để xác minh giả thuyết này:

import numpy as np 
%timeit [None] * 100000 
> 1000 loops, best of 3: 1.04 ms per loop 

%timeit np.array([0.0] * 100000) 
> 10 loops, best of 3: 21.3 ms per loop 
%timeit [i.__float__() for i in [0.0] * 100000] 
> 10 loops, best of 3: 32 ms per loop 


def flt(d): 
    try: 
     return float(d) 
    except: 
     return np.nan 

%timeit np.array([None] * 100000, dtype=np.float64) 
> 1 loops, best of 3: 477 ms per loop  
%timeit [flt(d) for d in [None] * 100000] 
> 1 loops, best of 3: 328 ms per loop 

Thêm một trường hợp khác chỉ để được rõ ràng về nơi tôi sẽ với điều này. Nếu có một kiểm tra rõ ràng cho Không, nó sẽ không được điều này chậm trên:

def flt2(d):        
    if d is None: 
     return np.nan 
    try: 
     return float(d) 
    except: 
     return np.nan 

%timeit [flt2(d) for d in [None] * 100000] 
> 10 loops, best of 3: 45 ms per loop 
+0

Tôi thấy giả thuyết của bạn rất thú vị, mặc dù sự khác biệt về thời gian mà bạn đang nhận được (khoảng 1.5X nhanh hơn) vẫn không hỗ trợ đối số của bạn vì sự khác biệt về thời gian của OP là khoảng 35X .... bạn có thể tiếp tục làm việc theo hướng này –

+0

@sgpc Vâng, nếu tôi muốn tìm hiểu kỹ hơn thì bước tiếp theo là xem xét nguồn. Mặc dù tôi biết: nếu họ đang kiểm tra một cách rõ ràng cho 'Không có', nó sẽ không chậm như vậy. – U2EF1

+1

Tôi đào sâu hơn. Mã được chi tiêu tất cả thời gian của nó ném execeptions. Nó không xử lý những thứ như dây nhiều như gọi getattr hoặc getbuffer cho rất nhiều thứ mà không có thuộc tính hoặc không phải là bộ đệm. Cả hai đều tạo và bỏ qua các ngoại lệ. Tôi đã điều chỉnh common.c và ctor.c để tránh những trường hợp này và hiệu suất giống như những gì bạn mong đợi. – MarkW

3

Tôi đã báo cáo vấn đề này là một vấn đề khó khăn. Báo cáo và vá files đang ở đây:

https://github.com/numpy/numpy/issues/3392

Sau vá:

# was 240 ms, best alternate version was 3.29 
In [5]: %timeit numpy.array([None]*100000) 
100 loops, best of 3: 7.49 ms per loop 

# was 353 ms, best alternate version was 9.65 
In [6]: %timeit numpy.array([[0.0]]*100000) 
10 loops, best of 3: 23.7 ms per loop