Numba中的乘法函数比CPython慢

时间:2014-06-28 21:28:38

标签: python performance cpython numba

我在python中编写了以下代码

from numba import *

def mul(a, b):
    return a * b

@jit
def numba_mul(a, b):
    return a * b


@jit(int_(int_, int_))
def numba_mul2(a, b):
    return a * b

并得到以下结果

In [3]: %timeit mul(10, 10)
10000000 loops, best of 3: 124 ns per loop

In [4]: %timeit numba_mul(10, 10)
1000000 loops, best of 3: 271 ns per loop

In [5]: %timeit numba_mul2(10, 10)
1000000 loops, best of 3: 263 ns per loop

为什么CPython的速度是Numba的2倍?这是在带有LLVM 3.2的OSX 10.9.3上的Python 2.7.7中

如果有帮助,llvm转储(使用numba --annotate --llvmp-dump main.py获得)低于

----------------LLVM DUMP <function descriptor 'numba_mul2$30'>-----------------
; ModuleID = 'module.numba_mul2$30'

define i32 @numba_mul2.int64.int64(i64*, i64 %arg.a, i64 %arg.b) {
entry:
  %a = alloca i64
  store i64 %arg.a, i64* %a
  %b = alloca i64
  store i64 %arg.b, i64* %b
  %a.1 = alloca i64
  %b.1 = alloca i64
  %"$0.1" = alloca i64
  br label %B0

B0:                                               ; preds = %entry
  %1 = load i64* %a
  store i64 %1, i64* %a.1
  %2 = load i64* %b
  store i64 %2, i64* %b.1
  %3 = load i64* %a.1
  %4 = load i64* %b.1
  %5 = mul i64 %3, %4
  store i64 %5, i64* %"$0.1"
  %6 = load i64* %"$0.1"
  store i64 %6, i64* %0
  ret i32 0
}

!python.module = !{!0}

!0 = metadata !{metadata !"__main__"}

================================================================================
-----------------------------------ANNOTATION-----------------------------------
# File: main.py
# --- LINE 30 --- 

@jit(int_(int_, int_))

# --- LINE 31 --- 

def numba_mul2(a, b):

    # --- LINE 32 --- 
    # label 0
    #   a.1 = a  :: int64
    #   b.1 = b  :: int64
    #   $0.1 = a.1 * b.1  :: int64
    #   return $0.1

    return a * b


================================================================================

1 个答案:

答案 0 :(得分:3)

您的测试太小,无法产生有意义的结果。如果您只是这样做:

def f():
    pass
%timeit f()

您可能会得到一段时间,这是您运行时间的重要部分。在我的机器上,mul功能的时间只有一半多一点。

另外,numba必须根据你的参数查找要调度的函数,然后将你的python整数转换为int32 / int64,然后创建一个新的python对象,将结果包装回来。

删除框/ unbox开销后尝试测试:

from numba import *

def mul(a, b):
    for i in range(1000):
        a * b

@jit
def numba_mul(a, b):
    for i in range(1000):
        a * b


@jit(int_(int_, int_))
def numba_mul2(a, b):
    for i in range(1000):
        a * b
    return a*b

我的机器上分别得到81.1μs,330 ns和322 ns用于此测试。

编辑:我很想知道numba中空函数调用的开销,所以我添加了以下测试:

def empty(a, b):
    pass

@jit
def numba_empty(a, b):
    pass

@jit
def numba_empty2(a, b):
    numba_empty(a,b)

此测试我得到155ns,333ns和348ns。似乎numba&gt; numba呼叫开销非常小。