我使用scipy的odeint运行一个相当大的ODE系统 . 为了使系统保持连贯,易于阅读和更短,我将大部分内容划分为相互调用的类 . 从可读性的角度来看,似乎工作正常,但是由于重复调用python对象,它会显着减慢实际的ODE求解器 . 我研究了优化代码的方法,以保持一定程度的可读性,同时使计算更有效率(使用Numba或使用Sympy将其转换为numpy-aware lambda函数),但是到目前为止我还没有成功 . 我想知道在这种情况下哪些策略可能会有所帮助 . 我在下面提供了一个简单的代码版本 . 先感谢您 .
class NaL():
g = 0
def I(self, v, E): return self.g * (v - E) #Leak current
class Neuron():
C_m = 1.0 #membrane capacitance
V = 0 # Voltage
m, h = 0, 0 #activating variables
def I_Na(self): #Sodium Currents
return self.NaT.I(self.V, self.m, self.h)+ self.NaL.I(self.V)
def __init__(self):
self.NaT = NaT()
self.NaL = NaL()
self.NaT.g = 3000
self.NaL.g = 20
I1 = Neuron()
def Run(X,t):
I1.V, I1.m, I1.h = X
dydt = [(0 - I1.I_Na()) / I1.C_m, #dV/dt for neuron
I1.NaT.dmdt(I1.V, I1.m), #dm/dt for sodium channel
I1.NaT.dhdt(I1.V, I1.h) #dh/dt for sodium channel
]
return dydt
X = odeint(Run, [-70, 0.0050, 0.9961], t)
1 回答
集成的瓶颈几乎可以肯定地评估衍 生产环境 品
Run
,因为必须在每个集成步骤中多次调用它 . 现在,由于所有类成员和函数调用,您在那里有相当大的Python开销 .对此的一个解决方案是使用您的模块JiTCODE,而不是定义积分器使用的函数,您可以象征性地定义微分方程(使用SymPy) . 然后将它们转换为C代码,将其编译为Python函数,然后将其用于集成 . 这样,您的类和类函数仅在实际集成之前被调用几次,并且集成与您在没有类和类似的情况下定义衍生函数时一样高效 . (另外,通过编译可以获得相当大的速度提升,特别是如果你有很多神经元 . )
就目前而言,您将示例翻译为JiTCODE非常简单:
由于示例代码不起作用的相同原因,此代码现在不起作用 . 请注意,类中涉及动态变量的所有算术都是符号化的 . 使用加法和乘法,这开箱即用,但如果您有
math.sin
或sympy.sin
之类的东西,则必须用sympy.sin
替换它 .