I am trying to optimize my python code. One of the bottlenecks comes when I tried to apply a function to a numpy array according to each element value. For instance, I have an array with thousand elements and I apply a function for values greater than a tolerance and another function (Taylor series) for the rest. I do masking but still slow, at least I'm calling the following functions for 64 millions times.
EPSILONZETA = 1.0e-6
ZETA1_12 = 1.0/12.0
ZETA1_720 = 1.0/720.0
def masked_condition_zero(array, tolerance):
""" Return the indices where values are lesser (and greater) than tolerance
"""
# search indices where array values < tolerance
indzeros_ = np.where(np.abs(array) < tolerance)[0]
# create mask
mask_ = np.ones(np.shape(array), dtype=bool)
mask_[[indzeros_]] = False
return (~mask_, mask_)
def bernoulli_function1(zeta):
""" Returns the Bernoulli function of zeta, vector version
"""
# get the indices according to condition
zeros_, others_ = masked_condition_zero(zeta, EPSILONZETA)
# create an array filled with zeros
fb_ = np.zeros(np.shape(zeta))
# Apply the original function to the values greater than EPSILONZETA
fb_[others_] = zeta[others_]/(np.exp(zeta[others_])-1.0)
# computes series for zeta < eps
zeta0_ = zeta[zeros_]
zeta2_ = zeta0_ * zeta0_
zeta4_ = zeta2_ * zeta2_
fb_[zeros_] = 1.0 - 0.5*zeta0_ + ZETA1_12 * zeta2_ - ZETA1_720 * zeta4_
return fb_
Now suppose you have an array zeta with negative and positive floats which changes in each loop that extends to 2^26 iterations and you want to compute fbernoulli_function1(zeta) each time.
There is a better solution ?
np.expm1(docs.scipy.org/doc/numpy/reference/generated/numpy.expm1.html) to compute the function. You'll still have to handle 0 separately, since0/expm1(0)givesnan, but the value (in the limit) should be 1. There is currently an open pull request at scipy for adding the functionexprel(x) = (exp(x)-1)/x: github.com/scipy/scipy/pull/4839; feel free to comment there if you like.