[英]How can I improve the performance of the below python code
我寫了如下所示的這段代碼。 我遇到了嚴重的性能問題。 尤其是我循環 5000 萬次的循環(對於 z in range(total):) 似乎很慢。 我可以修改它以提高效率嗎? - 也許修改它如何在 r1,r2 中存儲最后 10 個值的總和?
import numpy as np
import math
import scipy.stats as sp
# Define sample size
sample=4999999
cutoff=int((sample+1)/100)
# Define days for x-day VaR
xdays=10
# Calculate the whole sample size and extended total sample size
size=sample*xdays+xdays-1
total=size+xdays
cutoff_o=int((size+1)/100)
# Sample values for kurtosis
#kurt=[0.0000001,1.0,2.0,3.0,4.0,5.0,6.0,10.0]
kurt=[6.0]
# Number of repetitions
rep=2
# Define correlation coefficient
rho=0.5
# Loop for different iterations
for x in range(rep):
uni=sp.uniform.rvs(size=total)
# Loop for different values of kurtosis
for y in kurt:
df=(6.0/y)+4.0
# Initialize arrays
t_corr=np.empty(total)
n_corr=np.empty(total)
t_corr_2=np.empty(total)
r1=np.empty(sample)
r2=np.empty(size)
r3=np.empty(sample)
r4=np.empty(size)
# Define t dist from uniform
t_dist=sp.t.ppf(uni,df)
n_dist=sp.norm.ppf(uni)
# Loop to generate autocorrelated distributions
for z in range(total):
if z==0:
t_corr[z]=t_dist[z]
n_corr[z]=n_dist[z]
t_corr_2[z]=sp.t.ppf(sp.norm.cdf(n_corr[z]),df)
else:
t_corr[z]=rho*t_dist[z-1] + math.sqrt((1-rho**2))*t_dist[z]
n_corr[z]=rho*n_dist[z-1] + math.sqrt((1-rho**2))*n_dist[z]
t_corr_2[z]=sp.t.ppf(sp.norm.cdf(n_corr[z]),df)
if z>xdays-1:
z_x=int(z/xdays)-1
if (z%xdays)==0 and z_x<sample:
r1[z_x]= sum(t_corr[z-10:z])
r3[z_x]= sum(t_corr_2[z-10:z])
r2[z-xdays]= sum(t_corr[z-10:z])
r4[z-xdays]= sum(t_corr_2[z-10:z])
print (np.partition(r1, cutoff-1)[cutoff-1], np.partition(r3, cutoff-1)[cutoff-1], np.partition(r2, cutoff_o-1)[cutoff_o-1], np.partition(r4, cutoff_o-1)[cutoff_o-1])
print ()
一些建議:
首先,您可以從循環中刪除if
語句。 當程序員知道z
在第一個循環中等於 0 時,檢查z == 0
數百萬次似乎有點不必要。 if z>xdays-1
:
if z==0:
t_corr[z]=t_dist[z]
n_corr[z]=n_dist[z]
t_corr_2[z]=sp.t.ppf(sp.norm.cdf(n_corr[z]),df)
for z in range(1, xdays - 1):
t_corr[z]=rho*t_dist[z-1] + math.sqrt((1-rho**2))*t_dist[z]
n_corr[z]=rho*n_dist[z-1] + math.sqrt((1-rho**2))*n_dist[z]
t_corr_2[z]=sp.t.ppf(sp.norm.cdf(n_corr[z]),df)
for z in range(xdays - 1, total)
t_corr[z]=rho*t_dist[z-1] + math.sqrt((1-rho**2))*t_dist[z]
n_corr[z]=rho*n_dist[z-1] + math.sqrt((1-rho**2))*n_dist[z]
t_corr_2[z]=sp.t.ppf(sp.norm.cdf(n_corr[z]),df)
z_x=int(z/xdays)-1
if (z%xdays)==0 and z_x<sample:
r1[z_x]= sum(t_corr[z-10:z])
r3[z_x]= sum(t_corr_2[z-10:z])
r2[z-xdays]= sum(t_corr[z-10:z])
r4[z-xdays]= sum(t_corr_2[z-10:z])
請仔細檢查; 我只是把它扔了:)
一個廉價/黑客修復,實際上可以提供一些重要的好處! 您可以嘗試將您的 python 代碼編譯成二進制文件,例如使用 Cython。 我實際上用一個人為的但與您的示例沒有不同的示例對此進行了測試,我希望可以為您提供足夠的信息來開始。 假設我有以下 python 腳本:
import math
for j in range(1000):
for i in range(1000):
a = math.sqrt(i) * math.sqrt(j)
在我的 Ubuntu VM 上使用python3 fast.py
運行它需要持續 0.4 秒的實時時間。 運行以下內容:
$ cython3 --embed -o fast.c fast.py
$ gcc -I /usr/include/python3.4m/ -o fast fast.c -lpython3.4m
從我的 python 代碼生成一個.c
文件,並從它自動為我fast
編譯二進制文件。 現在運行可執行文件給了我 0.14 秒的平均實時時間 - 一個巨大的改進!
另一個問題可能與您的列表切片有關。 請記住,切片表示法每次都涉及創建一個新列表,這意味着您將使用四個切片創建大約 200,000,000 個新列表。 現在我不確定這會更快,但是您可以在不復制的情況下實現相同的行為,例如:
sum(t_corr[z-10:z])
可以替換為
sum(t_coor[i] for i in range(z, 10))
再次,將其修復為您真正想要的; 這只是一個概念片。
讓我知道這是否有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.