首页 文章

设计启发式编写与`scipy.integrate.odeint`交互的Python类?

提问于
浏览
2

简介

scipy.integrate.odeint需要作为其第一个参数,一个计算我们想要整合的变量的导数的函数(从现在开始,我将其称为 d_func ,"derivative function") .

d_func 必须由用户在Python代码中编写 . 使用Numba提高性能的一个好方法是 @jit (因为在集成期间多次调用 d_func ) .

d_func 足够复杂以至于需要一个Python类对象时,我对如何编写高性能代码有疑问 .

代码设置

这是我的代码的“卡通”:

  • 有一个名为 DynamicBox.py 的模块

  • 这个模块里面是一个Python类, DynamicBox

  • DynamicBox 有一堆属性

  • 其中一些属性是"phase variables" - 也就是说,它们是我有兴趣整合的数量

  • 这些属性中的一些是"parameters" - 也就是说,我用它们来计算相位变量的导数

我将有一堆函数将采用 DynamixBox 阶段变量或参数属性,以便计算衍生物中的相关项 . 那是:

  • 我会 d_func

  • d_func 本身将使用 DynamixBox 属性调用许多小辅助函数来计算导数中的相关项

设计选择

我必须做出选择,有以下选择:

  • 或者我可以使 d_func 及其所有辅助函数方法 DynamicBox ;

  • 或者我只能使 d_func 的方法 DynamicBox ,并且它的所有辅助函数与 DynamicBox 在同一个模块中,但不是 DynamicBox 的方法;

  • 或只有辅助函数是 DynamicBox 的方法,但 d_func 只是在同一个模块( DynamicBox.py )中,而不是 DynamicBox 的方法;

  • 或者辅助函数和d_func都不是DynamicBox的方法 .

问题

我不太了解Python以找出最佳选择 . 我认为需要回答以下问题 .

  • Is it expensive to make instance attribute calls to get attributes or is it expensive only if you are in a function that is not a method of the class?

  • What if Numba is in play? For instance, will Numba like it better if I am @jit-ting normal functions instead of class methods?

1 回答

  • 2

    我可以评论这个问题的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 参数,如果函数必须回退到任何(慢)Python代码,这将导致Numba引发错误 . 这个 nopython 参数是确保您的Numba功能尽可能高效的好方法 .

相关问题