为什么在使用列表时用numba计算总和会慢一些?

2024-10-04 03:16:36 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我的密码:

@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 per loop (mean ± std. dev. of 7 runs, 100 loops each)

相反,如果没有jit,它会更快。你知道吗

137 µs ± 1.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


Tags: ofindevloopforrunsrangerandom
1条回答
网友
1楼 · 发布于 2024-10-04 03:16:36

因为numba(默默地)复制了列表,所以速度比较慢。你知道吗

要理解为什么会发生这种情况,你需要知道numba有object模式和nopython模式。在对象模式下,它可以对Python数据结构进行操作,但是它不会比普通Python函数快很多,甚至更慢(至少在一般情况下,很少有例外)。在nopython模式下,numba不能操作像list这样的Python数据结构,因此为了list的工作,它必须使用非Python列表。要从Python列表创建这样一个非Python列表(称为反射列表),必须复制和转换列表内容。你知道吗

在您的案例中,这种复制和转换会使它慢得多。你知道吗

这也是为什么人们通常应该避免在numba函数中使用非数组参数或返回的原因。数组的内容不需要转换,至少如果numba支持数组的数据类型,那么这些是“安全的”。你知道吗

如果这些数据结构(列表、元组、集合)被限制在numba中,它们就可以了——但是,当它们越过numba⭤Python边界时,它们必须被复制,这(几乎)总是会抵消所有性能增益。你知道吗


仅展示函数如何使用数组执行:

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倍。你知道吗

相关问题 更多 >