【问题标题】:Why doesn't numba optimize subroutines called in the code?为什么 numba 不优化代码中调用的子程序?
【发布时间】:2017-09-23 01:27:31
【问题描述】:

我是 numba 的新手,我尝试使用 @jit 来加速 Python 程序,但这只会影响我的代码。当我的代码调用另一个子程序时,似乎这个子程序在执行前没有得到优化。

当然,我可以@jit 装饰所有功能,但是对于我只使用的功能(不是我自己开发的),这是有限的。

请参阅以下基于 π 的莱布尼茨公式的示例。

def leibniz1(n):
    operand = 1.0
    result = 0.0
    for i in xrange(1, n*2, 2):
        result += operand / i
        operand = - operand
    return result * 4

leibniz1(10000000) 的运行时间:大约。 0.8 秒

当我添加时

from numba import jit, int32

并用@jit 装饰函数

@jit
def leibniz2(n):
    operand = 1.0
    result = 0.0
    for i in xrange(1, n*2, 2):
        result += operand / i
        operand = - operand
    return result * 4

10000000 次迭代的运行时间减少到大约。 0.1 秒。

问题来了:

@jit
def leibniz3(n):
     return leibniz1(n)

我希望 leibniz3 得到优化,leibniz1 也是如此 - 因为它是从优化的函数中调用的。但事实并非如此,运行时间再次约为。 0.8 秒,这是纯 leibniz1 值。

有没有机会用 numba 或类似的东西来实现我的计划,因为我不能 @jit 装饰我的程序所依赖的所有功能,因为它们不是我的。

【问题讨论】:

  • 首先 - Numba 仅支持(以某种方式加速)相当有限的 Python 范围,因此如果您无法访问这些函数,您可能会发现您也无法使其工作出色地。其次,你总是可以使用jitted_function = numba.jit(<insert optional signature>)(some_other_module.function) [- 记住装饰器只是一个函数调用!] 来 jit 不是你写的函数。

标签: python optimization jit numba


【解决方案1】:

首先我推荐使用 nopython 参数:

@jit(nopython=True)
def f(x):
    ....

通过这种方式,您可以强制像 C/Fortran 一样编译您的函数,如果这样做失败,您会得到一个明确的错误。 来自Documentation

Numba 有两种编译模式:nopython 模式和 object 模式。前者生成的代码要快得多,但有一些限制可以迫使 Numba 退回到后者。为了防止 Numba 回退,而是引发错误,请传递 nopython=True。

在文档中也有说明:

@jit 装饰器必须添加到任何此类库函数中,否则 Numba 可能会生成更慢的代码。

基本上,您的问题与您想在纯 C/Fortran 中从高级语言调用函数相同。 所以不幸的是,据我所知,除了在接近机器的代码中重新实现其他功能之外,没有其他解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    相关资源
    最近更新 更多