我尝试优化下面的代码,但我无法弄清楚如何提高计算速度。下面的代码运行差不多30秒。由于bootsam和filedata矩阵,这需要时间。有人可以帮我优化这段代码 是否有可能改善表现?
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
答案 0 :(得分:5)
基础代数:执行x = x * 1.23
360次可轻松转换为单次执行
x = x * (1.23 ** 360)
重构你的代码,你会发现不需要循环。
答案 1 :(得分:2)
如果没有看到真实的代码,很难回答。我无法让您的示例正常工作,因为balance
在代码的早期设置为inf
,因为在问题的评论中已经注意到了这一点。无论如何,一个非常明显的优化是不会在每次迭代时读取bootsam[mn-1,bs]
元素五次以计算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
)的运行速度比我原来的Acer Aspire上的原始代码快两倍。
<强>更新强>
如果您需要进一步优化,您至少可以做两件事:
filedata
的每个被访问元素处添加1并转换为float。而是在创建时向数组添加1并为其提供float数据类型。以下代码遵循这些建议:
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
通过这些更改,代码的运行速度几乎是之前优化代码的两倍。