【问题标题】:Weird performance issue for numba.jit function calling another numba.jit functionnumba.jit 函数调用另一个 numba.jit 函数的奇怪性能问题
【发布时间】:2018-01-16 16:08:56
【问题描述】:

当父函数调用子函数时,我注意到一些奇怪的性能结果,并且这两个函数都是numba.jit 编译的。谁能解释这种行为(下面的代码)?更重要的是,这个问题到底有没有解决?

为什么这很重要:假设我正在编写一个长而复杂的函数,我希望使用 numba.jit 编译来加速它。将子过程包装到子函数中是有意义的;然后由父函数调用。如果父函数和子函数都需要即时编译,那么我会遇到这个问题(即性能无明显原因下降)。

代码:

import time
import numpy
import numba


@numba.jit('void(int64[:])', nopython=True)
def bubble_sort(array):
    n = len(array)
    for _ in range(n):
        for i in range(n):
            if i+1 < n and array[i] > array[i+1]:
                temp = array[i]
                array[i] = array[i+1]
                array[i+1] = temp


@numba.jit('void(int64[:])')
def nested_with_jit(array):
    bubble_sort(array)


def nested_without_jit(array):
    bubble_sort(array)


if __name__ == '__main__':
    n = 50000
    array = numpy.arange(n).astype(numpy.int64)

    print('bubble_sort(array)')
    for i in range(5):
        start = time.time()
        bubble_sort(array)
        end = time.time()
        print('\t#{:d}: ~{:.4f} seconds'.format(i, end - start))

    print('nested_with_jit(array)')
    for i in range(5):
        start = time.time()
        nested_with_jit(array)
        end = time.time()
        print('\t#{:d}: ~{:.4f} seconds'.format(i, end - start))

    print('nested_without_jit(array)')
    for i in range(5):
        start = time.time()
        nested_without_jit(array)
        end = time.time()
        print('\t#{:d}: ~{:.4f} seconds'.format(i, end - start))

输出:

bubble_sort(array)
    #0: ~1.9890 seconds
    #1: ~1.9710 seconds
    #2: ~1.9840 seconds
    #3: ~1.9830 seconds
    #4: ~1.9880 seconds
nested_with_jit(array)
    #0: ~2.4730 seconds
    #1: ~2.4690 seconds
    #2: ~2.4620 seconds
    #3: ~2.4640 seconds
    #4: ~2.4380 seconds
nested_without_jit(array)
    #0: ~1.9780 seconds
    #1: ~1.9880 seconds
    #2: ~1.9880 seconds
    #3: ~1.9910 seconds
    #4: ~1.9880 seconds

【问题讨论】:

  • 这可能很有用。我只是在我的机器(i7-8700K)上使用 llvmlite-0.29.0、numba-0.45.1、python 3.6.8、ubuntu 18.10 运行上面的代码。 〜1.9178 用于bubble_sort,〜1.4993 用于nested_with_jit,〜1.9202 用于nested_without_jit。因此,对于现代版本的 numba 来说,嵌套函数可能不是问题

标签: python python-3.x numba


【解决方案1】:

我认为您可能会看到类型检查和分派的一些小开销,尽管由于某种原因在我的机器上(OSX py2.7 numba 0.36.1),我看到的开销较小(调用 1.45 秒) bubble_sort 直接和 1.63 秒使用 nested_with_jit 调用它)。如果我在bubble_sortnested_with_jit 上都使用没有显式类型的numba.jit(nopython=True),则差异基本上消失了。

【讨论】:

  • “类型检查和调度”消耗 0.2 秒(或 OP 系统上的 0.5 秒)似乎不合理。在 3 GHz 时,这是 600-15 亿个时钟周期!
  • 当我查看inspect_types 的输出时,我可以看到的唯一区别是指定类型的函数版本将数组标记为A(任何布局),而一个这允许 numba 使用基于输入的类型推断,它是C(连续内存布局)。如有疑问,请在 Numba gitter 上提问,也许开发人员可能会有一些见解 gitter.im/numba/numba
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
相关资源
最近更新 更多