2013-03-01 85 views
0

我試着優化下面的代碼,但我無法弄清楚如何提高計算速度。下面的代碼需要將近30秒才能運行。這是因爲bootsam和filedata矩陣需要時間。有人可以幫助我優化此代碼 是否有可能提高性能?Python:如何優化此代碼

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)'與'101'是一回事。' – mgilson 2013-03-01 05:05:41

+1

如果你說你正在用代碼做什麼而不是詢問如何改進它,這可能會有所幫助。 – 2013-03-01 05:07:06

+0

使用'timeit'模塊,如果你想檢查它所花費的時間量爲 – avasal 2013-03-01 05:08:28

回答

2

如果沒有看到真實的代碼就很難回答。我無法讓您的示例工作,因爲balance在代碼早期設置爲inf,因爲它在問題的註釋中已被注意到。無論如何,一個非常明顯的優化是不要在每次迭代中讀取五次元素以計算變量xxbal。所有這些變量使用相同的bootsam元素,所以你應該曾經看過的元素和重用:

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])) 

優化的代碼(它使用一個假值balance)幾乎運行兩次的速度比我的老宏碁原來的卓望。

更新

如果您需要進一步的優化,你可以做至少兩兩件事:

  • 不要加1,並轉換爲浮動在每filedata訪問元素。相反,在創建時向數組添加1,併爲其賦予一個float數據類型。
  • 不使用算術表達式混合numpy的和內置的數字,因爲Python中的運算工作慢(你可以閱讀更多關於在this SO thread這個問題)

下面的代碼如下的建議:

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 

通過這些更改,代碼的運行速度比先前優化的代碼快兩倍。

+0

感謝您查看代碼。你的評論確實節省了我的時間。現在我已經從行中替換了變量,並能夠在15秒內執行代碼。而不是30秒。 – Invincible 2013-03-03 04:14:20

+0

我已經在我的本地機器上運行代碼,並且能夠執行此代碼。請您進一步優化此代碼 – Invincible 2013-03-03 04:15:49

+0

請查看更新的答案。 – Vicent 2013-03-03 13:00:07

5

基本代數:執行x = x * 1.23 360倍,可以很容易地轉換爲

x = x * (1.23 ** 360)

一個執行重構代碼,你會看到,實際上並不需要的循環。

+0

我已經更新了代碼。請再次看看 – Invincible 2013-03-01 08:45:13