【问题标题】:Nested Numba function performance嵌套 Numba 函数性能
【发布时间】:2019-03-22 00:22:50
【问题描述】:

目前我正在尝试提高我的 python 代码的性能。为此,我成功地使用了 numba。为了改进我的代码结构,我创建了函数。现在我惊讶地注意到,如果我将代码拆分为不同的 numba 函数,代码比我将整个代码放在一个带有 numba 装饰器的函数中要慢得多。 一个例子是:

@nb.njit
def fct_4(a, b):
    x = a ^ b
    setBits = 0
    while x > 0:
        setBits += x & 1
        x >>= 1
    return setBits


@nb.njit
def fct_3(c, set_1, set_2):
    h = 2
    if c not in set_1 and c not in set_2:
        if fct_4(0, c) <= h:
            set_1.add(c)
        else:
            set_2.add(c)


@nb.njit
def fct_2(c, set_1, set_2):
    fct_3(c, set_1, set_2)


@nb.njit
def fct_1(set_1, set_2):
    for x1 in range(1000):
        c = 2
        fct_2(c, set_1, set_2)

比

慢
@nb.njit
def fct_1(set_1, set_2):
    for x1 in range(1000):
        c = 2       
        h = 2
        if c not in set_1 and c not in set_2:
            if fct_4(0, c) <= h:
                set_1.add(c)
            else:
                set_2.add(c)

与

@nb.njit
def main_fct(set_1, set_2):
    for i in range(50):
        for x in range(1000):
            fct_1(set_1, set_2)

set_1 = {0}
set_2 = {47}

start = timeit.default_timer()
main_fct(set_1, set_2)
stop = timeit.default_timer()

(2.70 秒对 0.46 秒)。我认为这不应该有所作为。你能启发我吗?

【问题讨论】:

  • 1) 您测量运行时和编译时间的混合。在计时之前运行一次函数以获得运行时。 2) LLVM 后端决定是内联函数还是调用它,如果函数没有内联,则预期会有差异。 3)对于一个小例子,你的功能真的很复杂。 Numba 不能直接处理列表或字典,它们被转换为非常昂贵的内部表示。也许这种开销没有针对嵌套函数进行优化,导致性能不佳。
  • 我可以强制 LLVM 倾斜函数吗?签名有用吗?我应该避免使用集合吗?

标签: python numba


【解决方案1】:

由于python是一种动态类型语言,它的函数调用开销是相当高的。

除此之外,您正在循环调用函数,因此调用函数和检查参数所产生的执行时间乘以 1000 倍。

【讨论】:

  • 但是所有函数最初都是用numba编译的。因此,我认为应该没有区别。
  • 否则我想我应该避免创建太多单独的函数。或者有没有办法通过添加签名来提高性能?
  • 你考虑编译时间了吗?在您的情况下,这也可能会增加额外的时间开销。从 Python 3.6 开始,您可以将参数保持为静态,但我认为它不会提高性能。但是,对于您的程序,我建议您从大局来看 - 为什么您有多个级别的循环,您是否需要让事情如此模块化等,然后做出决定
猜你喜欢
  • 1970-01-01
  • 2018-07-14
  • 2013-11-15
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 2023-03-22
  • 2016-12-05
相关资源
最近更新 更多