这是我的代码:
@numba.jit( )
def dis4(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
x1=[random.random() for _ in range(m)]
x2=[random.random() for _ in range(m)]
%timeit dis4(x1,x2)
每个循环3.32 ms±37.8 µs(平均±标准偏差,共运行7次,每个循环100个循环)
相反,如果没有jit
,它将更快。
每个循环137 µs±1.62 µs(平均±标准偏差,共运行7次,每个10000个循环)
答案 0 :(得分:1)
速度较慢,因为numba(无声)复制了列表。
要了解为什么为什么,您需要知道numba具有对象模式和nopython模式。在对象模式下,它可以在Python数据结构上运行,但是它不会比普通的Python函数快得多,甚至不会慢(至少在一般情况下,有非常罕见的例外)。在nopython模式下,numba无法对list
之类的Python数据结构进行操作,因此,为了使list
正常工作,它必须使用非Python列表。要从Python列表中创建这样的非Python列表(称为反射列表),必须复制并转换列表内容。
这种复制和转换会使您的情况变慢得多。
这也是为什么通常应该避免使用非数组参数或使用numba函数返回的原因。数组的内容不需要进行转换,至少在numba支持数组的dtype的情况下,这样才是“安全的”。
如果将这些数据结构(列表,元组,集合)限制在numba中,则它们很好-但是,当这些数据结构超出numbaPython边界时,则必须复制它们(几乎)总是使所有性能提升无效。
仅演示函数如何对数组执行:
import math
import random
import numba as nb
import numpy as np
def dis4_plain(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
@nb.jit
def dis4(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
m = 10_000
x1 = [random.random() for _ in range(m)]
x2 = [random.random() for _ in range(m)]
a1 = np.array(x1)
a2 = np.array(x2)
时间:
dis4(x1, x2)
dis4(a1, a2)
%timeit dis4_plain(x1, x2)
# 2.71 ms ± 178 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit dis4(x1, x2)
# 24.1 ms ± 279 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit dis4(a1, a2)
# 14 µs ± 608 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
因此,使用列表和numba.jit
的速度要慢10倍,而使用数组的jitted函数要比使用列表的Python函数快200倍。