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

时间:2015-05-03 17:12:19

标签: python design-patterns scipy numba

简介

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

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

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

代码设置

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

  • 有一个名为DynamicBox.py
  • 的模块 此模块中的
  • 是Python类DynamicBox
  • DynamicBox有一堆属性
  • 其中一些属性是“阶段变量” - 也就是说,他们是我有兴趣整合的数量
  • 其中一些属性是“参数” - 也就是说,我使用它们 计算相变量的导数

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

  • 我将有d_func
  • d_func本身会调用许多小辅助函数 使用DynamixBox计算衍生工具中的相关字词 属性

设计选择

我必须做出选择,并提供以下选项:

  1. 要么我可以使d_func及其所有辅助函数方法 DynamicBox;
  2. 或者我只能d_func DynamicBox的方法,     并且它的所有辅助函数都在同一个模块中     DynamicBox,但不是DynamicBox;
  3. 的方法
  4. 或只有辅助函数是DynamicBox的方法,但是 d_func位于同一模块(DynamicBox.py)中,而不是a DynamicBox;
  5. 的方法
  6. 或者辅助函数和d_func都不是方法 DynamicBox。
  7. 问题

    我不太了解Python以确定哪个选择最佳。我认为需要回答以下问题。

    • 使实例属性调用获取属性是否昂贵,或者仅当您处于不是方法的函数时才会很昂贵 班级?

    • 如果Numba在比赛中怎么办?例如,如果我@jit - 正常函数而不是类方法,Numba会更喜欢它吗?

1 个答案:

答案 0 :(得分: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函数尽可能高效的好方法。