Рассмотрим следующий простой тест:
import numpy as np
from timeit import timeit
a = np.random.randint(0,2,1000000,bool)
Давайте найдем индекс первого True
timeit(lambda:a.argmax(), number=1000)
# 0.000451055821031332
Это достаточно быстро из-за короткого замыкания numpy
.
Он также работает на смежных ломтиках,
timeit(lambda:a[1:-1].argmax(), number=1000)
# 0.0006490410305559635
Но, похоже, не на несмежных. Я был в основном заинтересован в поиске последнего True
:
timeit(lambda:a[::-1].argmax(), number=1000)
# 0.3737605109345168
ОБНОВЛЕНИЕ: Мое предположение, что наблюдаемое замедление было вызвано не коротким замыканием, является неточным (спасибо @Victor Ruiz). Действительно, в наихудший сценарий массива all
False
b=np.zeros_like(a)
timeit(lambda:b.argmax(), number=1000)
# 0.04321779008023441
мы все еще на порядок быстрее, чем в несмежных кейс. Я готов принять объяснение Виктора, что настоящий виновник выполняется копия (время принудительного копирования с помощью
.copy()
наводит на мысль). После этого уже не имеет значения, происходит короткое замыкание или нет.
Но другие размеры шагов! = 1 приводят к аналогичному поведению.
timeit(lambda:a[::2].argmax(), number=1000)
# 0.19192566303536296
Вопрос: почему numpy
не закорачивает ОБНОВЛЕНИЕ без копирования в последних двух примерах?
И, что еще более важно: есть ли обходной путь, то есть какой-то способ заставить numpy
выполнить короткое замыкание ОБНОВЛЕНИЕ, не копируя также на несмежные массивы?