2017-10-10 5 views
0

Je suis en train d'écrire une simulation de la croissance de la population de cellules cancéreuses, et j'utilise les fonctions numpy.random pour modéliser les cellules qui acquièrent ou perdent des mutations. J'ai déterminé par le profilage que le goulot d'étranglement dans le code (environ 70% de l'exécution) est les premières lignes qui contiennent les fonctions de numpy.random. Ici, la variable num_steps est un grand nombre, environ un million:Améliorer la vitesse des fonctions numpy.random

def simulate(mu, gamma, beta, num_steps, threshold): 
    mutation_num = 0 # the index of the mutation (we assume each mutation only occurs once) 
    population = {() : 1} # represents population: tuple of mutations and number of cells with those mutations 
    for epoch in range(num_steps): 
     next_population = {} 
     for mutations, size in population.items():  
      born = np.random.binomial(size, birth_rate) 
      if np.random.binomial(born, gamma): 
       return True 
      mut_loss = 0 # initializing in case variable is not created 
      if mutations: 
       mut_gain, mut_loss, mut_same = np.random.multinomial(born, [mu, beta, 1-mu-beta]) 
      else: 
       mut_gain, mut_same = np.random.multinomial(born, [mu, 1-mu]) 
..... 

Y at-il un moyen de rendre les fonctions np.random.binomial et np.random.multinomial courir plus vite? J'ai essayé d'utiliser Cython, mais cela n'a pas aidé.

+0

Vous pouvez commencer par remplacer 'range' par' xrange' qui est un équivalent paresseux et voir comment cela aide; ou remplacez cela avec un certain temps et incrémenter la valeur manuellement (ce qui est effectivement la même optimisation). –

+0

@BurhanKhalid L'observation 'range' vs.' xrange' n'est vraie que pour Python 2. Es-tu certain que OP n'utilise pas Python 3? –

+0

J'utilise python 3. Comme je l'ai déjà mentionné, le profileur indique que le goulot d'étranglement est autour des fonctions aléatoires numpy. – Alex

Répondre

2

Pour illustrer mon commentaire:

In [81]: timeit np.random.binomial(1,1,1000) 
46.4 µs ± 1.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 
In [82]: %%timeit 
    ...: for _ in range(1000): 
    ...:  np.random.binomial(1,1) 
    ...: 
4.77 ms ± 186 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

Si possible de générer beaucoup de valeurs aléatoires avec un appel plutôt qu'un à la fois.

+0

Merci, ça m'a beaucoup aidé! – Alex