nathano
nathano

Reputation: 21

Is there any way to make Python random sum code faster in Cython?

I have written a piece of coded that draws random numbers from a uniform distribution, totals them until it reaches a number L=x. I have tried to optimise it using Cython but i would like any suggestions on how it could be further optimised as it would be called for large L values so would take quite long. This is the code I have written in Jupyter so far

%%cython
import numpy as np
cimport numpy 
import numpy.random

def f(int L):
    cdef double r=0
    cdef int i=0
    cdef float theta
    while r<=L:
        theta=np.random.uniform(0, 2*np.pi, size = None)
        r+=np.cos(theta)
        i+=1    
    return i

I'd like to speed it up as much as possible

Upvotes: 2

Views: 63

Answers (1)

Ethan
Ethan

Reputation: 1373

One way, without using Cython, that you can speed this up is to call np.random.uniform less frequently. The cost of calling this function and returning 1 value vs 100,000 values is negligible, call it and returning 1,000 values vs calling it 1,000 times reaps huge time savings:

def call1000():
    return [np.random.uniform(0, 2*np.pi, size = None) for i in range(1000)]

%timeit call1000()
762 µs ± 3.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.random.uniform(0, 2*np.pi, size = 1000)
10.8 µs ± 13.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

You can implement this and ensure that you don't run out of values by doing something like this:

def f(L):
    r = 0
    i = 0
    j = 0
    theta = np.random.uniform(0, 2*np.pi, size = 100000)
    while r<=L:
        if j == len(theta):
            j=0
            theta=np.random.uniform(0, 2*np.pi, size = 100000)
        r+=np.cos(theta[j])
        i+=1    
    return i

Upvotes: 1

Related Questions