Wygląda na to, że można znacznie zwiększyć wydajność, jeśli pracujemy z liniowo indeksowanymi tablicami. Oto wektorowy realizacja rozwiązać naszą sprawę, podobnie jak @rth's answer, ale przy użyciu indeksowania liniowy -
# Get floor-ed indices
idx = np.floor(input).astype(np.int)
# Calculate linear indices
lin_idx = idx[:,0]*lat_len + idx[:,1]
# Index raveled/flattened version of binary_matrix with lin_idx
# to extract and form the desired output
out = input[binary_matrix.ravel()[lin_idx] ==1]
Tak więc, krótko mówiąc mamy:
out = input[binary_matrix.ravel()[idx[:,0]*lat_len + idx[:,1]] ==1]
Runtime testy -
Ta sekcja porównuje proponowane podejście w tym rozwiązaniu przeciwko other solution, które wykorzystuje indeksowanie wiersza-kolumny.
Case # 1 (datasizes oryginalne):
In [62]: lat_len = 100 # lattice length
...: input = np.random.random(size=(1000,2)) * lat_len
...: binary_matrix = np.random.choice(2, lat_len * lat_len).
reshape(lat_len, -1)
...:
In [63]: idx = np.floor(input).astype(np.int)
In [64]: %timeit input[binary_matrix[idx[:,0], idx[:,1]] == 1]
10000 loops, best of 3: 121 µs per loop
In [65]: %timeit input[binary_matrix.ravel()[idx[:,0]*lat_len + idx[:,1]] ==1]
10000 loops, best of 3: 103 µs per loop
Case # 2 (Większe datasizes):
In [75]: lat_len = 1000 # lattice length
...: input = np.random.random(size=(100000,2)) * lat_len
...: binary_matrix = np.random.choice(2, lat_len * lat_len).
reshape(lat_len, -1)
...:
In [76]: idx = np.floor(input).astype(np.int)
In [77]: %timeit input[binary_matrix[idx[:,0], idx[:,1]] == 1]
100 loops, best of 3: 18.5 ms per loop
In [78]: %timeit input[binary_matrix.ravel()[idx[:,0]*lat_len + idx[:,1]] ==1]
100 loops, best of 3: 13.1 ms per loop
Zatem zwiększenie wydajności z tego liniowego indeksowania wydaje się być o 20%
- 30%
.
Niewiarygodne. Czy możesz wyjaśnić, co zmieniło największą różnicę w wydajności, np. Użycie int? –
Różnica w wydajności wynika z tego, że unikamy pętli for w pythonie i zamiast tego używamy zaawansowanego indeksowania numpy (dodałem powyższy link), który jest kodowany bardziej efektywnie w C. Przesyłanie do liczb całkowitych jest tylko efektem ubocznym, ponieważ indeksy nie mogą mieć typu float 'dtype' i muszą być liczbami całkowitymi lub boolean. – rth