Arrays numpy.数组(列表)运行缓慢
我有一个500万整数的列表。我想用numpy数组来覆盖这个列表。我尝试了以下代码:Arrays numpy.数组(列表)运行缓慢,arrays,performance,list,numpy,cython,Arrays,Performance,List,Numpy,Cython,我有一个500万整数的列表。我想用numpy数组来覆盖这个列表。我尝试了以下代码: numpy.array( list ) 但是它非常慢 我对这个操作进行了100次基准测试,并对列表进行了100次循环。没有太大区别 有什么好主意可以让它更快吗?我觉得这很快,我查了一下时间: import numpy as np import time start_time = time.time() number = 1 elements = 10000000 your_list = [number] *
numpy.array( list )
但是它非常慢
我对这个操作进行了100次基准测试,并对列表进行了100次循环。没有太大区别
有什么好主意可以让它更快吗?我觉得这很快,我查了一下时间:
import numpy as np
import time
start_time = time.time()
number = 1
elements = 10000000
your_list = [number] * elements
ret = np.zeros(shape=(len(your_list)))
np.copyto(ret, your_list)
print("--- %s seconds ---" % (time.time() - start_time))
--- 0.7615997791290283 seconds ---
如果你有,你可以创建一个更快的函数。但只是一个警告:如果列表中有无效元素(不是整数或太大的整数),它将崩溃
我在这里使用IPython魔术(%load\u ext cython
和%cython
),重点是展示函数的外观,而不是展示如何编译cython代码(这并不难,Cythons“how compile”文档非常好)
以及时间安排:
import numpy as np
def other(your_list): # the approach from @Damian Lattenero in the other answer
ret = np.zeros(shape=(len(your_list)), dtype=int)
np.copyto(ret, your_list)
return ret
inp = list(range(1000000))
%timeit np.array(inp)
# 315 ms ± 5.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.array(inp, dtype=int)
# 311 ms ± 2.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit other(inp)
# 316 ms ± 3.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit to_array(inp)
# 23.4 ms ± 1.15 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
因此它的速度快了10倍多。列出一个大的小整数列表;使用
numpy
拐杖:
In [619]: arr = np.random.randint(0,256, 5000000)
In [620]: alist = arr.tolist()
In [621]: timeit alist = arr.tolist() # just for reference
10 loops, best of 3: 108 ms per loop
以及纯列表迭代的时间(不做任何事情)
生成指定数据类型的数组
In [623]: arr8 = np.array(alist, 'uint8')
In [624]: timeit arr8 = np.array(alist, 'uint8')
1 loop, best of 3: 508 ms per loop
我们可以通过ITER的获得2倍的改进;显然,它的检查更少np.array
即使列表是数字和字符串的混合,也可以使用。它还处理列表列表等
In [625]: timeit arr81 = np.fromiter(alist, 'uint8')
1 loop, best of 3: 249 ms per loop
当我们在整个过程中进行数学运算时,使用数组的优势变得显而易见:
In [628]: timeit arr8.sum()
100 loops, best of 3: 6.93 ms per loop
In [629]: timeit sum(alist)
10 loops, best of 3: 74.4 ms per loop
In [630]: timeit 2*arr8
100 loops, best of 3: 6.89 ms per loop
In [631]: timeit [2*i for i in alist]
1 loop, best of 3: 465 ms per loop
众所周知,使用数组要比使用列表快,但是有一个很大的“启动”开销 你的列表只包含整数,你是正数吗?结果数组的数据类型是什么?是的,我对此非常肯定。它是图像数据的平面阵列。所以输入和输出数组都是uint8type@user3201090我更新了我的答案,普雷维乌斯号速度不快,这一个我很困惑。你说list
是一个整数列表,但在评论中说它是图像数据的平面数组
和uint8
。Python整数不是uint8
。如果它不是一个ndarray
,它是一个bytestring`?什么是“非常慢”?这么慢,交互完成时会出现延迟?或者转换1000张这些“图像”时速度较慢?为什么在整个列表中循环会更快?@user3201090我想说的是,copyto中没有重新分配,因为ret
已经分配并且形状正确,这就是为什么会这样fast@SeverinPappadeux,OP说的是我以前的一次尝试,使用for循环真的比np.array(您的_列表)
快吗?我做了一些计时,但没有更快。请注意,np.zeros
给出了一个float
数组,但问题指定了一个int
数组。@MSeifert我尝试过这个方法。它比NP.ARM(更快)快。由于现在的性能改进,我现在可以处理35个FPS的视频,最重要的是,不必重写C++中的几千行代码。虽然在我的Mac上它只快了5倍。@沂南也可以使用<代码> CDEF NP。UInt8YT[[:] ARR= NP。0(LeN(InP),dType=NP.UInt8)< /C>(需要cimport numpy作为np
以及导入numpy作为np
)。该操作基本上是带宽受限的,因此选择尽可能最小的数据类型可以显著加快速度。我在mac上使用windows的时间太长,可能是int32
,因此它可以解释为什么您的数据类型看起来慢了一倍。您的“数字”是原来的两倍。
In [625]: timeit arr81 = np.fromiter(alist, 'uint8')
1 loop, best of 3: 249 ms per loop
In [628]: timeit arr8.sum()
100 loops, best of 3: 6.93 ms per loop
In [629]: timeit sum(alist)
10 loops, best of 3: 74.4 ms per loop
In [630]: timeit 2*arr8
100 loops, best of 3: 6.89 ms per loop
In [631]: timeit [2*i for i in alist]
1 loop, best of 3: 465 ms per loop