-
-
Notifications
You must be signed in to change notification settings - Fork 11.3k
Closed
Description
Numpy uses different functions for power internally:
- When the exponent is in
{-1, 0, 0.5, 1, 2}
, it uses respectively{reciprocal, one_like, sqrt, ~identity, square}
. - For any other exponent, it uses a much slower routine.
Therefore, calling a **= 2; a **= -1
is much faster than a **= -2
.
I guess it could be possible to improve the logic in fast_scalar_power
to also handle the cases {-2, -0.5}
, cf. scikit-learn/scikit-learn#9277 (comment)
A benchmark on a **= b; a **= -1
versus a **= -b
gives me (v1.11.3):
(Click on details to show the script)
import numpy as np
from time import time
import matplotlib.pyplot as plt
n_points = int(1e6)
power_range = np.arange(0, 4.1, 0.1)
durations = np.zeros((2, power_range.size))
array = np.random.randn(n_points)
np.abs(array, array)
for i, power in enumerate(power_range):
array_copy = array.copy()
start = time()
array_copy **= -power
durations[0, i] = time() - start
array_copy = array.copy()
start = time()
array_copy **= power
array_copy **= -1
durations[1, i] = time() - start
plt.figure(figsize=(10, 4))
ax = plt.gca()
ax.plot(power_range, durations[0], '-o', label='one operation')
ax.plot(power_range, durations[1], '-o', label='two operations')
ax.set(xlabel='power', ylabel='time', title='Elementwise power in Numpy')
ax.legend()
plt.show()
jnothman, eric-wieser, ketozhang and dankal444