Speed ​​up double loop in Python

Is there a way to speed up a double loop that updates its values ​​from a previous iteration?

In code:

def calc(N, m): x = 1.0 y = 2.0 container = np.zeros((N, 2)) for i in range(N): for j in range(m): x=np.random.gamma(3,1.0/(y*y+4)) y=np.random.normal(1.0/(x+1),1.0/sqrt(x+1)) container[i, 0] = x container[i, 1] = y return container calc(10, 5) 

As you can see, the inner loop updates the variables x and y, and the outer loop starts with a different value of x each time. I do not think this is vectorized, but other improvements may be possible.

Thank!

+4
optimization python loops numpy micro-optimization
Jul 19 '13 at 2:26
source share
2 answers

I do not think that this will be connected with any important speed, but you can save some function calls if you immediately generate all your gamma and normally distributed random values.

Gamma functions have a scaling property, so if you draw the value x from the gamma distribution (k, 1), then c*x will be the value obtained from the gamma distribution (k, c). Similarly, with a normal distribution, you can take the y value obtained from the normal (0, 1) and convert it to the value obtained from the normal distribution (m, s), which performs x*s + m . Thus, you can rewrite your function as follows:

 def calc(N, m): x = 1.0 y = 2.0 container = np.zeros((N, 2)) nm = N*m gamma_vals = np.random.gamma(3, 1, size=(nm,)) norm_vals = np.random.normal(0, 1, size=(nm,)) for i in xrange(N): for j in xrange(m): ij = i*j x = gamma_vals[ij] / (y*y+4) y = norm_vals[ij]/np.sqrt(x+1) + 1/(x+1) container[i, 0] = x container[i, 1] = y return container 

If the actual parameters of your distributions had a simpler expression, you may be able to use some complex form of np.cumprod or the like, as well as save yourself from loops. I can’t figure out how to do this ...

+1
Jul 19 '13 at 5:48
source share

It works?

 for i in xrange(N): # xrange is an iterator, range makes a new list. # You save linear space and `malloc`ing time by doing this x += m*y # a simple algebra hack. Compute this line of the loop just once instead of `m` times y -= m*x y *= -1 # another simple algebra hack. Compute this line of the loop just once instead of `m` times container[i,0] = x container[i,1] = y return container 
0
Jul 19. '13 at 2:31 on
source share



All Articles