我正在使用scipy的odeint运行一个相当大的ode系统。为了保持系统的连贯性、易读性和简短性,我将其大部分分成类来互相调用。从可读性的角度来看,它似乎工作得很好,但是由于对python对象的重复调用,它显著地减慢了实际的ODE解算器的速度。我四处寻找优化代码的方法,以保持一定程度的可读性,同时也使其在计算上更高效(在将其转换为numpy感知lambda函数之前使用Numba或使用Sympy),但是到目前为止我还不是很成功。我想知道在这种情况下什么策略会有帮助。我提供了下面代码的一个简单版本。提前谢谢你。在
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)
集成的瓶颈几乎肯定是求导
Run
,因为在集成的每个步骤中都必须多次调用它。现在,由于所有的类成员和函数调用,这里有相当多的Python开销。在解决这个问题的一个方法是使用你的模块JiTCODE,在这里,你不用定义积分器要使用的函数,而是象征性地定义微分方程(用SymPy)。然后将它们转换为C代码,然后将其编译为Python函数,然后将其用于集成。这样,您的类和类函数只在实际的集成之前被调用几次,并且集成与您定义没有类和类似类的派生类时一样有效。(此外,通过编译,您可能会获得相当大的速度提升,特别是如果您有许多神经元的话)
现在,将示例转换为JiTCODE很简单:
这段代码现在不工作,原因与示例代码不工作的原因相同。请注意,类中所有涉及动态变量的算法都会变成符号。对于加法和乘法,这是开箱即用的,但是如果有}之类的东西,就必须用
math.sin
或{sympy.sin
来代替它。在相关问题 更多 >
编程相关推荐