2012-08-03 27 views
10

Tôi đang cố gắng sử dụng và tăng tốc việc lập chỉ mục ưa thích để "nối" hai mảng và tổng kết một trục của kết quả.Nhanh chóng (er) lập chỉ mục và giảm thiểu numpy ưa thích?

Something như thế này:

$ ipython 
In [1]: import numpy as np 
In [2]: ne, ds = 12, 6 
In [3]: i = np.random.randn(ne, ds).astype('float32') 
In [4]: t = np.random.randint(0, ds, size=(1e5, ne)).astype('uint8') 

In [5]: %timeit i[np.arange(ne), t].sum(-1) 
10 loops, best of 3: 44 ms per loop 

Có một cách đơn giản để đẩy nhanh tiến độ tuyên bố trong In [5]? Tôi có nên sử dụng OpenMP và một số thứ như scipy.weave hoặc Cython 's prange?

+0

Một câu hỏi liên quan khác là làm cách nào để tôi sử dụng 'pandas' để làm điều tương tự? – npinto

+0

Numpy đang làm điều đó ở tốc độ C, do đó bạn có thể sẽ không thể tăng tốc độ lên nhiều với dệt. – reptilicus

Trả lời

8

numpy.take nhanh hơn nhiều so với lập chỉ mục ưa thích vì một lý do nào đó. Bí quyết duy nhất là nó xử lý mảng bằng phẳng.

In [1]: a = np.random.randn(12,6).astype(np.float32) 

In [2]: c = np.random.randint(0,6,size=(1e5,12)).astype(np.uint8) 

In [3]: r = np.arange(12) 

In [4]: %timeit a[r,c].sum(-1) 
10 loops, best of 3: 46.7 ms per loop 

In [5]: rr, cc = np.broadcast_arrays(r,c) 

In [6]: flat_index = rr*a.shape[1] + cc 

In [7]: %timeit a.take(flat_index).sum(-1) 
100 loops, best of 3: 5.5 ms per loop 

In [8]: (a.take(flat_index).sum(-1) == a[r,c].sum(-1)).all() 
Out[8]: True 

Tôi nghĩ chỉ có cách nào khác bạn sẽ thấy nhiều sự cải thiện tốc độ vượt này sẽ được để viết một hạt nhân tùy chỉnh cho một GPU sử dụng một cái gì đó giống như PyCUDA.

+1

Nó chỉ xử lý mảng theo mặc định, bạn vẫn có thể sử dụng từ khóa 'axis'. Tức là, 'np.take (np.arange (10) .reshape ((- 1,2)), [0], axis = 0)' sẽ chọn hàng đầu tiên. – jorgeca

+0

@jorgeca: đúng, nhưng tôi không nghĩ rằng bạn có thể kéo các phần tử riêng lẻ bằng cách chỉ định cả hàng và cột như bạn có thể với chỉ mục lạ mắt trừ khi bạn lập chỉ mục mảng phẳng. – user545424

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