2013-03-01 4 views
0

J'ai essayé d'optimiser le code ci-dessous mais je n'arrive pas à comprendre comment améliorer la vitesse de calcul. Le code ci-dessous prend presque 30 secondes à courir. cela prend du temps à cause de la matrice bootsam et filedata. Quelqu'un peut-il m'aider s'il vous plaît à optimiser ce code Est-il possible d'améliorer la performance?Python: comment optimiser ce code

import numpy as np 
filedata=np.genfromtxt('monthlydata1970to2010.txt',dtype='str') # this will creae 980 * 7 matrix 
nboot=5000 
results=np.zeros((11,nboot)); #this will create 11*5000 matrix 
results[0,:]=600 
horizon=360 
balance=200 
bootsam=np.random.randint(984, size=(984, nboot)) # this will create 984*5000 matrix 
for bs in range(0,nboot): 
    for mn in range(1,horizon+1): 
     if mn%12 ==1: 
      bondbal = 24*balance 
      sp500bal=34*balance 
      russbal = 44*balance 
      eafebal=55*balance 
      cashbal =66*balance 
      bondbal=bondbal*(1+float(filedata[bootsam[mn-1,bs]-1,2])) 
      sp500bal=sp500bal*(1+float(filedata[bootsam[mn-1,bs]-1,3])) 
      russbal=russbal*(1+float(filedata[bootsam[mn-1,bs]-1,4])) 
      eafebal=eafebal*(1+float(filedata[bootsam[mn-1,bs]-1,5])) 
      cashbal=cashbal*(1+float(filedata[bootsam[mn-1,bs]-1,6])) 
      balance=bondbal + sp500bal + russbal + eafebal + cashbal 
     else: 
      bondbal=bondbal*(1+float(filedata[bootsam[mn-1,bs]-1,2])) 
      sp500bal=sp500bal*(1+float(filedata[bootsam[mn-1,bs]-1,3])) 
      russbal=russbal*(1+float(filedata[bootsam[mn-1,bs]-1,4])) 
      eafebal=eafebal*(1+float(filedata[bootsam[mn-1,bs]-1,5])) 
      cashbal=cashbal*(1+float(filedata[bootsam[mn-1,bs]-1,6])) 
      balance=bondbal + sp500bal + russbal + eafebal + cashbal 
      if mn == 60: 
       results[1,bs]=balance 
      if mn == 120: 
       results[2,bs]=balance 
      if mn == 180: 
       results[3,bs]=balance 
      if mn == 240: 
       results[4,bs]=balance 
      if mn == 300: 
       results[5,bs]=balance 
+1

'1 + float (100)' est la même chose que '101.' – mgilson

+1

Il serait probablement utile si vous disiez ce que vous essayiez de faire avec le code au lieu de demander comment l'améliorer. –

+0

utilisez le module 'timeit' si vous voulez vérifier le temps qu'il prend – avasal

Répondre

2

Il est difficile de répondre sans voir le vrai code. Je ne peux pas faire fonctionner votre échantillon car balance est défini sur inf au début du code, comme cela a été remarqué dans les commentaires à la question. De toute façon, une optimisation assez évidente est de ne pas lire l'élément bootsam[mn-1,bs] cinq fois à chaque itération afin de calculer les variables xxbal. Toutes ces variables utilisent le même élément bootsam de sorte que vous devriez lire l'élément une fois et le réutiliser:

for bs in xrange(0,nboot): 
    for mn in xrange(1,horizon+1): 
     row = bootsam[mn-1,bs]-1 
     if (mn % 12) == 1: 
      bondbal = 24*balance 
      sp500bal=34*balance 
      russbal = 44*balance 
      eafebal=55*balance 
      cashbal =66*balance 

      bondbal=bondbal*(1+float(filedata[row,2])) 
      sp500bal=sp500bal*(1+float(filedata[row,3])) 
      russbal=russbal*(1+float(filedata[row,4])) 
      eafebal=eafebal*(1+float(filedata[row,5])) 
      cashbal=cashbal*(1+float(filedata[row,6])) 
      balance=bondbal + sp500bal + russbal + eafebal + cashbal 
     else: 
      bondbal=bondbal*(1+float(filedata[row,2])) 
      sp500bal=sp500bal*(1+float(filedata[row,3])) 
      russbal=russbal*(1+float(filedata[row,4])) 
      eafebal=eafebal*(1+float(filedata[row,5])) 
      cashbal=cashbal*(1+float(filedata[row,6])) 

Le code optimisé (qui utilise une valeur fausse pour balance) fonctionne presque deux fois plus rapide que l'original sur mon ancien Acer Aspirer.

Mise à jour

Si vous avez besoin d'optimisations supplémentaires que vous pouvez faire au moins deux choses:

  • ne pas ajouter 1 et convertir à flotter à chaque élément accessible de filedata. Au lieu de cela, ajoutez 1 au tableau au moment de la création et donnez-lui un type de données flottant.
  • ne pas utiliser des expressions arithmétiques qui mélangent numpy et nombres intégrés en raison arithmétique Python fonctionne plus lent (vous pouvez en savoir plus sur ce problème dans this SO thread)

Le code suivant suit ces conseils:

filedata=np.genfromtxt('monthlydata1970to2010.txt',dtype='str') # this will creae 980 * 7 matrix 
my_list = (np.float(1) + filedata.astype(np.float)).tolist() # np.float is converted to Python float 
nboot=5000 
results=np.zeros((11,nboot)) #this will create 11*5000 matrix 
results[0,:]=600 
horizon=360 
balance=200 
bootsam=np.random.randint(5, size=(984, nboot)) # this will create 984*5000 matrix 
for bs in xrange(0,nboot): 
    for mn in xrange(1,horizon+1): 
     row = int(bootsam[mn-1,bs]-1) 
     if (mn % 12) == 1: 
      bondbal = 24*balance 
      sp500bal=34*balance 
      russbal = 44*balance 
      eafebal=55*balance 
      cashbal =66*balance 

      bondbal=bondbal*(my_list[row][2]) 
      sp500bal=sp500bal*(my_list[row][3]) 
      russbal=russbal*(my_list[row][4]) 
      eafebal=eafebal*(my_list[row][5]) 
      cashbal=cashbal*(my_list[row][6]) 
      balance=bondbal + sp500bal + russbal + eafebal + cashbal 
     else: 
      bondbal=bondbal*(my_list[row][2]) 
      sp500bal=sp500bal*(my_list[row][3]) 
      russbal=russbal*(my_list[row][4]) 
      eafebal=eafebal*(my_list[row][5]) 
      cashbal=cashbal*(my_list[row][6]) 
      balance=bondbal + sp500bal + russbal + eafebal + cashbal 

Avec ces modifications, le code est presque deux fois plus rapide que le code précédemment optimisé.

+0

merci de regarder dans le code. Vos commentaires me font vraiment gagner du temps. Maintenant, j'ai remplacé la variable de la ligne et capable d'exécuter du code en 15 secondes. au lieu de 30 sec. – Invincible

+0

J'ai exécuté le code sur ma machine locale et je suis capable d'exécuter ce code. Pouvez-vous s'il vous plaît optimiser davantage ce code? – Invincible

+0

Jetez un oeil à la réponse mise à jour s'il vous plaît. – Vicent

5

Algèbre de base: l'exécution x = x * 1.23 360 fois peut être facilement converti en une seule exécution de

x = x * (1.23 ** 360)

Refactoriser votre code et vous verrez que les boucles ne sont pas vraiment nécessaires.

+0

J'ai mis à jour le code. S'il vous plaît jeter un oeil à nouveau – Invincible