Во-первых, вы просто выполняете более сложную последовательность операций. Для каждого входа ваша функция ceil / clip делает следующее:
- Входное значение меньше 0? Если это так, установите промежуточное значение равным 0.
- В противном случае оно больше 1? Если это так, установите промежуточное значение равным 1.
- В противном случае установите промежуточное значение для входного значения.
- Рассчитать верхний предел промежуточного значения и установить выходное значение.
(Это происходит в два этапа, один, где все отсечение сделано, другой, когда все потолки сделаны.)
Вы синхронизируете это с параметрами, которые делают следующее для каждого ввода:
- Выполните сравнение> = между входом и 0 и установите выход на него.
Не удивительно, что> = быстрее.
Во-вторых, ваша функция ceil / clip записывает в 16 раз больше байтов, чем> =. Символ> = производит один байт вывода для каждого элемента ввода (view
- это представление, поэтому копирование данных там отсутствует), в то время как ваша функция ceil / clip создает промежуточный массив и выходной массив, оба типа dtype float64.
В-третьих, у предиктора ветки плохое время с этим clip
в случайном массиве. Он не знает, какая ветвь будет использоваться каждый раз. Более предсказуемый массив проходит clip
намного быстрее:
In [21]: %timeit X.clip(0, 1)
1 loop, best of 5: 211 ms per loop
In [22]: A = np.full_like(X, 0.5)
In [23]: %timeit A.clip(0, 1)
10 loops, best of 5: 86.6 ms per loop
Наконец, по крайней мере на машине и сборке NumPy, на которой я тестировал, numpy.ceil
просто удивительно медленен:
In [24]: %timeit np.ceil(X)
10 loops, best of 5: 166 ms per loop
Я не уверен, ударяет ли он по программной ceil
реализации или как. Вероятно, это будет отличаться на разных сборках.