Python 为什么我的代码在函数形式上慢得多?
我不久前写了一段代码,它使用文本文件中的数据处理光谱并对其进行计算。我从一个代码开始,它一行一行地执行所有操作,没有任何函数,尽管很长,但它在2.11秒内完成运行(根据Python 为什么我的代码在函数形式上慢得多?,python,python-2.7,performance,function,Python,Python 2.7,Performance,Function,我不久前写了一段代码,它使用文本文件中的数据处理光谱并对其进行计算。我从一个代码开始,它一行一行地执行所有操作,没有任何函数,尽管很长,但它在2.11秒内完成运行(根据%%timeit)。下面是原始代码,标记为 但是,我希望将代码放在函数中,以便将来在不同的模型中更易于阅读和使用。尽管我使用的步骤与以前相同(但这次是在我的函数中),但速度要慢得多。此代码也在下面。现在,我必须等待大约15-20分钟才能获得相同的输出。为什么它会慢得多,有没有什么方法可以让它大大加快,但仍然使用函数 原始代码: i
%%timeit
)。下面是原始代码,标记为
但是,我希望将代码放在函数中,以便将来在不同的模型中更易于阅读和使用。尽管我使用的步骤与以前相同(但这次是在我的函数中),但速度要慢得多。此代码也在下面。现在,我必须等待大约15-20分钟才能获得相同的输出。为什么它会慢得多,有没有什么方法可以让它大大加快,但仍然使用函数
原始代码:
import re
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
filename = 'bpass_spectra.txt'
extinctionfile = 'ExtinctionLawPoints.txt' # from R_V = 4.0
pointslist = []
datalist = []
speclist = []
# Constants
Msun = 1.98892e30 # solar mass [kg]
h = 4.1357e-15 # Planck's constant [eV s]
c = float(3e8) # speed of light [m/s]
# Read spectra file
f = open(filename, 'r')
rawspectra = f.readlines()
met = re.findall('Z\s=\s(\d*\.\d+)', rawspectra[0])
del rawspectra[0]
for i in range(len(rawspectra)):
newlist = rawspectra[i].split(' ')
datalist.append(newlist)
# Read extinction curve data file
rawpoints = open(extinctionfile, 'r').readlines()
for i in range(len(rawpoints)):
newlst = re.split('(?!\S)\s(?=\S)|(?!\S)\s+(?=\S)', rawpoints[i])
pointslist.append(newlst)
pointslist = pointslist[3:]
lambdalist = [float(item[0]) for item in pointslist]
k_abslist = [float(item[4]) for item in pointslist]
xvallist = [(c*h)/(lamb*1e-6) for lamb in lambdalist]
k_interp = scipy.interpolate.interp1d(xvallist, k_abslist)
# Create new lists
Elist = [float(item[0]) for item in datalist]
speclambdalist = [h*c*1e9/E for E in Elist]
z1list = [float(item[1]) for item in datalist]
speclist.extend(z1list)
met = met[0]
klist = [None]*len(speclist)
Loutlist = [None]*len(speclist)
Tlist = [None]*len(speclist)
# Define parameters
b = 2.0
R = 1.0
z = 1.0
Mgas = 1.0 # mass of gas, input
Mhalo = 2e41 # mass of dark matter halo, known
if float(met) > 0.0052:
DGRlist = [50.0*np.exp(-2.21)*float(met)]*len(speclist)
elif float(met) <= 0.0052:
DGRlist = [((50.0*float(met))**3.15)*np.exp(-0.96)]*len(speclist)
for i in range(len(speclist)):
if float(Elist[i]) <= 4.1357e-3: # frequencies <= 10^12 Hz
klist[i] = 0.1*(float(Elist[i])/(1000.0*h))**b # extinction law [cm^2/g]
elif float(Elist[i]) > 4.1357e-3: # frequencies > 10^12 Hz
klist[i] = k_interp(Elist[i]) # interpolated function's value at Elist[i]
Mdustlist = [Mgas*DGR for DGR in DGRlist] # dust mass
Rhalo = 0.784*(0.27**2.0)*(0.7**(-2.0/3.0))*float(10.0/(1.0+z))*((Mhalo/(1e8*Msun))**(1.0/3.0))
Rdust = 0.018*Rhalo # [kpc]
for i in range(len(speclist)):
Tlist[i] = 3*Mdustlist[i]*klist[i]/(4*np.pi*Rdust)
Linlist = [float(spectra)*R for spectra in speclist]
# Outgoing luminosity as function of wavelength
for i in range(len(Linlist)):
Loutlist[i] = Linlist[i]*np.exp(-Tlist[i])
# Test the calculation
print "LIN ELEMENTS 0 AND 1000:", Linlist[0], Linlist[1000]
print "LOUT ELEMENTS 0 AND 1000:", Loutlist[0], Loutlist[1000]
重新导入
将matplotlib.pyplot作为plt导入
将numpy作为np导入
导入scipy.interpolate
文件名='bpass\u spectra.txt'
灭绝文件='extractionlawpoints.txt'#来自R_V=4.0
pointslist=[]
数据列表=[]
speclist=[]
#常数
Msun=1.98892e30#太阳质量[kg]
h=4.1357e-15#普朗克常数[eV s]
c=浮子(3e8)#光速[m/s]
#读取光谱文件
f=打开(文件名“r”)
rawspectra=f.readlines()
met=re.findall('Z\s=\s(\d*\.\d+),rawspectra[0])
del rawspectra[0]
对于范围内的i(len(RawSpectrum)):
newlist=rawspectra[i]。拆分(“”)
追加(newlist)
#读取消光曲线数据文件
rawpoints=open(灭绝文件'r')。readlines()
对于范围内的i(len(原始点)):
newlst=re.split('(?!\S)\S(?=\S)|(?!\S)\S+(?=\S'),原始点[i])
pointslist.append(newlst)
pointslist=pointslist[3:]
lambdalist=[pointslist中的项的浮点值(项[0])]
k_abslist=[pointslist中项目的浮动(项目[4])]
xvallist=[(c*h)/(lamb*1e-6)表示lambdalist中的lamb]
k_interp=scipy.interpolate.interp1d(xvallist,k_abslist)
#创建新列表
Elist=[datalist中项目的浮动(项目[0])]
speclambdalist=[h*c*1e9/E表示Elist中的E]
z1list=[数据列表中项目的浮动(项目[1])]
speclist.extend(z1list)
met=met[0]
klist=[None]*len(speclist)
Loutlist=[None]*len(规格列表)
Tlist=[None]*len(speclist)
#定义参数
b=2.0
R=1.0
z=1.0
Mgas=1.0#气体质量,输入
Mhalo=2e41#暗物质晕的质量,已知
如果浮动(met)>0.0052:
DGRlist=[50.0*np.exp(-2.21)*浮点(met)]*len(speclist)
elif浮动(met)0.0052:
DGRlist=[50.0*np.exp(-2.21)*金属丰度]*len(规格表)#尘气比
elif金属丰度仍不可读。函数不应该那么长。@首先,这不能解决我的性能问题。其次,最终目标是能够简单地使用许多不同的参数调用dust(…)
,而不必做任何其他事情,不幸的是,它需要许多任务/代码行。请尝试在子函数中对此进行分解。这真的很难理解(包括你自己在3个月内…)将代码放入函数并不会显著降低速度,如果有的话。这里还有一些事情很难发现,因为你的代码对于缺乏你的领域专业知识的人来说很难理解。我注意到在第一个示例中,您在一个循环中调用了一个scipy函数kinterp。在第二个循环中,您调用了一个python函数interpolate,它似乎是一个类似的循环。但它们并不是等价的,因为插值是一个非常复杂的函数,在调用kinterp之前需要进行一系列的数字运算。这可能是您的性能问题。将其分解为更小的函数所造成的性能损失应该可以忽略不计
import re
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
# Required files and lists
filename = 'bpass_spectra.txt' # number of columns = 4
extinctionfile = 'ExtinctionLawPoints.txt' # R_V = 4.0
datalist = []
if filename == 'bpass_spectra.txt':
filetype = 4
else:
filetype = 1
if extinctionfile == 'ExtinctionLawPoints.txt':
R_V = 4.0
else:
R_V = 1.0 #to be determined
# Constants
M_sun = 1.98892e30 # solar mass [kg]
h = 4.1357e-15 # Planck's constant [eV s]
c = float(3e8) # speed of light [m/s]
# Inputs
beta = 2.0
R = 1.0
z = 1.0
M_gas = 1.0
M_halo = 2e41
# Read spectra file
f = open(filename, 'r')
rawlines = f.readlines()
met = re.findall('Z\s=\s(\d*\.\d+)', rawlines[0])
del rawlines[0]
for i in range(len(rawlines)):
newlist = rawlines[i].split(' ')
datalist.append(newlist)
# Read extinction curve data file
rawpoints = open(extinctionfile, 'r').readlines()
def interpolate(R_V, rawpoints, Elist, j):
pointslist = []
if R_V == 4.0:
for i in range(len(rawpoints)):
newlst = re.split('(?!\S)\s(?=\S)|(?!\S)\s+(?=\S)', rawpoints[i])
pointslist.append(newlst)
pointslist = pointslist[3:]
lambdalist = [float(item[0]) for item in pointslist]
k_abslist = [float(item[4]) for item in pointslist]
xvallist = [(c*h)/(lamb*1e-6) for lamb in lambdalist]
k_interp = scipy.interpolate.interp1d(xvallist, k_abslist)
return k_interp(Elist[j])
# Dust extinction function
def dust(interpolate, filetype, datalist, beta, R, z, M_gas, M_halo, met):
speclist = []
if filetype == 4:
metallicity = float(met[0])
Elist = [float(item[0]) for item in datalist]
speclambdalist = [h*c*1e9/E for E in Elist]
met1list = [float(item[1]) for item in datalist]
speclist.extend(met1list)
klist, Tlist = [None]*len(speclist), [None]*len(speclist)
if metallicity > 0.0052:
DGRlist = [50.0*np.exp(-2.21)*metallicity]*len(speclist) # dust to gas ratio
elif metallicity <= 0.0052:
DGRlist = [((50.0*metallicity)**3.15)*np.exp(-0.96)]*len(speclist)
for i in range(len(speclist)):
if Elist[i] <= 4.1357e-3: # frequencies <= 10^12 Hz
klist[i] = 0.1*(float(Elist[i])/(1000.0*h))**beta # extinction law [cm^2/g]
elif Elist[i] > 4.1357e-3: # frequencies > 10^12 Hz
klist[i] = interpolate(R_V, rawpoints, Elist, i) # interpolated function's value at Elist[i]
Mdustlist = [M_gas*DGR for DGR in DGRlist] # dust mass
R_halo = 0.784*(0.27**2.0)*(0.7**(-2.0/3.0))*float(10/(1+z))*((M_halo/(1e8*M_sun))**(1.0/3.0))
R_dust = 0.018*R_halo # [kpc]
# Optical depth calculation
Tlist = [3*Mdustlist[i]*klist[i]/(4*np.pi*R_dust) for i in range(len(speclist))]
# Ingoing and outgoing luminosities as functions of wavelength
Linlist = [float(spectra)*R for spectra in speclist]
Loutlist = [Linlist[i]*np.exp(-Tlist[i]) for i in range(len(speclist))]
return speclambdalist, Linlist, Loutlist
print dust(interpolate, filetype, datalist, beta, R, z, M_gas, M_halo, met)