简介
scipy.integrate.odeint
需要一个函数作为其第一个参数,该函数计算我们想要积分的变量的导数(从现在开始我将其称为 d_func,即“导数函数”)。
d_func
必须由用户用 Python 代码编写。使用 Numba 提高性能的一个好方法是 @jit
d_func
(因为 d_func
被称为many 积分期间的次数)。
当 d_func 足够复杂以至于需要一个 Python 类对象支持时,我对如何编写高性能代码有疑问。
代码设置
这是我的代码的“卡通”:
- 有一个名为
DynamicBox.py
的模块 - 此模块内部是一个 Python 类,
DynamicBox
DynamicBox
有一堆属性- 其中一些属性是“相位变量”——也就是说,它们是我有兴趣积分的量
- 其中一些属性是“参数”——也就是说,我用它们来 计算相位变量的导数
我将有一堆函数,它们将采用DynamixBox
相变量或参数属性,以便计算导数中的相关项。即:
- 我将有一个
d_func
d_func
本身会调用很多小辅助函数来 使用 DynamixBox 计算导数中的相关项 属性
设计选择
我必须做出选择,有以下选项:
- 我可以制作
d_func
及其所有辅助函数方法动态框
; - 或者我只能将
d_func
设为DynamicBox
的方法, 它的所有辅助函数都在同一个模块中DynamicBox
,但不是DynamicBox
的方法; - 或者只有辅助函数是
DynamicBox
的方法,但是d_func
只是在同一个模块 (DynamicBox.py
) 中,而不是DynamicBox
的方法; - 或者辅助函数和 d_func 都不是 动态框。
问题
我对 Python 的了解不够,无法确定哪种选择是最好的。我认为需要回答以下问题。
进行实例属性调用来获取属性是否昂贵,或者仅当您处于非方法的函数中时才昂贵 类(class)的?
如果 Numba 正在比赛怎么办?例如,如果我
@jit
使用普通函数而不是类方法,Numba 会更喜欢它吗?
最佳答案
我可以评论这个问题的 Numba 部分。
正如其他用户所提到的,Numba 中的属性访问会导致一些开销。例如,您可能会想编写如下代码:
class Foo(object):
def __init__(self, x):
self.x = x
@numba.jit
def dosomething(self, y):
for i in range(len(self.x)):
self.x[i] += y[i]
这会很慢,因为 Numba 每次遇到 self.x
时都必须调用 Python 层进行属性访问。
做同样事情的更好方法是这样的:
class Foo(object):
def __init__(self, x):
self.x = x
def dosomething(self, y):
_dosomething(self.x, y)
@numba.jit(nopython=True)
def _dosomething(x, y):
for i in range(len(x)):
x[i] += y[i]
这里循环内没有属性访问,此外我们还可以添加 nopython=True
参数,如果函数必须回退,这将导致 Numba 引发错误任何(慢)Python 代码。这个 nopython
参数是确保您的 Numba 函数尽可能高效的好方法。
关于python - 设计启发式方法来编写与 `scipy.integrate.odeint` 交互的 Python 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016845/