为什么在这个例子中列表比numpy快?numpy通常被认为比使用列表更快?但这里的列表似乎快了2倍以上?
$ python main.py
using_list: 1.8105032444000244 seconds
using_numpy: 4.414405345916748 seconds
个字符
使用Python 3.10.
作为参考,我发现使用numba
中的@njit
将极大地改进我的numpy代码。但我想知道为什么我的普通numpy版本比列表慢这么多?有没有一种方法可以让我的普通numpy版本更快,而不使用numba
。
using_numba: 0.6930002999997669 seconds
from numba import njit
@njit
def using_numba(N):
x = np.ones(N)
y = np.zeros(N)
for i in range(1, N):
y[i] = x[i] + 0.5 * (y[i-1] - x[i])
的字符串
3条答案
按热度按时间ybzsozfc1#
迭代或使用索引逐个元素访问numpy数组效率很低(请参考Why is for loop on native python list faster than for loop on numpy array)。考虑使用numpy的内置函数或方法来加速循环,这可以显着提高大型数组的性能:
个字符
使用
N = 100000
进行基准测试:型
zpqajqem2#
为了从numpy中获得好处,您需要以不同的方式进行计算。将其视为对所有值的全局操作,而不是迭代计算:
例如,这个函数给出了相同的结果,但运行速度比使用列表快25倍:
字符串
如果您需要更快的速度,您可以合并更简单的操作(例如加法和乘法而不是取幂):
型
xlpyo6sf3#
当Numpy可以隐式地并行化操作时,它是快速的。如果没有
y[i-1] -> y[i]
数据依赖项,可以替换如下循环字符串
与
型
迭代数组的元素并不比迭代列表的元素更快,实际上由于需要在Numpy值类型和Python原生类型之间来回转换,因此速度稍慢。
例如,
float
值的列表只是引用的列表。y[i]
是对存在于列表之外的float
值的引用。然而,dtype
的float64
数组只是一个表示浮点值集合的二进制blob。像y[i]
这样的操作必须提取适当的位,然后使用它们来 * 创建 * 一个要返回的float
值。更复杂的表达式,如型
需要从
x
和y
中提取 * 三个 * 这样的值,执行与列表方法相同的运算,然后将结果转换回字节序列以插入回y
。对于
y = 0.5*x
,不存在字节序列到float
值的转换,不使用float.__mul__
,也不转换回字节序列。所有算法都在Numpy的优化C代码中内部完成。