Python2D列表性能,无numpy
我正在尝试用Python创建一个2D列表。我发现了两种可能性Python2D列表性能,无numpy,python,numpy,Python,Numpy,我正在尝试用Python创建一个2D列表。我发现了两种可能性 def cArray(size): c = [[0. for i in range(size)] for j in range(size)] return c def npArray(size): np = numpy.zeros((size,size)) return np 现在这两个函数都给出了正确的答案。这里的问题在于性能。我使用timeit运行了这两个程序,下面是我的结果: list siz
def cArray(size):
c = [[0. for i in range(size)] for j in range(size)]
return c
def npArray(size):
np = numpy.zeros((size,size))
return np
现在这两个函数都给出了正确的答案。这里的问题在于性能。我使用timeit运行了这两个程序,下面是我的结果:
list size is 5000
number of times run is 5
cArray average time: 3.73241295815
npArray average time: 0.210782241821
所以很明显,我想避免使用第一种解决方案,特别是因为它将在100k以下的尺寸下运行。但是,我也不想使用太多的依赖项。有没有一种方法可以让我在不使用numpy的情况下高效地创建2D阵列?它不需要完全跟上速度,只要速度不慢17倍。我尝试了几种选择 编辑:原来的耳环有问题,它创建了对同一列表的引用 Edit2:根据塞巴斯蒂安的建议添加了
array.array
import time
import numpy as np
import array
t1 = 0
def starttimer():
global t1
t1 = time.clock()
def stoptimer(s):
t2 = time.clock()
print 'elapsed time for "{}": {:.3f} seconds'.format(s, t2-t1)
def cArray(size):
c = [[0. for i in range(size)] for j in range(size)]
return c
def dArray(size):
d = [[0. for i in xrange(size)] for j in xrange(size)]
return d
def eArray2(size):
return [[0.]*size for j in xrange(size)]
def fArray(size):
return np.zeros((size,size))
def gArray(size):
return [array.array('d', [0])*size for j in xrange(size)]
sz = 5000
starttimer()
cArray(sz)
stoptimer('cArray')
starttimer()
dArray(sz)
stoptimer('dArray')
starttimer()
fArray(sz)
stoptimer('fArray')
starttimer()
gArray(sz)
stoptimer('gArray')
结果(如果有人关心的话,FreeBSD amd64上的cpython 2.7.3):
如果您想达到真正的低级别,可以使用
ctypes
:
a = (ctypes.c_int * 5000 * 5000)()
但是NumPy在运行Python的大多数平台上都是可用的
所以很明显,我想避免使用第一种解决方案,特别是因为它将在100k以下的尺寸下运行。但是,我也不想使用太多的依赖项
你必须选择其中哪一个对你更重要。Numpy具有更好的性能,正是因为它不使用内置的Python类型,而是使用自己的类型,这些类型针对数值计算进行了优化。如果您的数据将是数字的,并且将有10万行/列,那么您将看到numpy的性能有了巨大的提高。如果你想避免numpy依赖,你将不得不忍受性能下降。(显然,您可以编写自己的Python库或C扩展来针对特定用例进行优化,但这些库和其他库一样都是依赖项。)
就我个人而言,我建议你只使用numpy。它的应用如此广泛,以至于任何考虑使用处理100k多维数组的库的人都可能已经安装了numpy。我的使用案例是,在一些在线judge平台上,库的依赖性是有限的,但在进行动态编程时需要2D数组(也很难矢量化)。我的python代码经常超过时间限制 有一些事情需要提醒:
import timeit
size = 1000
range_init_0 = "size={}".format(size)
range_init_1 = "a = [[0 for i in range(size)] for j in range(size)]"
multi_init_0 = "size={}".format(size)
multi_init_1 = "a = [[0]*size for _ in range(size)]"
numpy_init_0 = "from numpy import zeros; size={}".format(size)
numpy_init_1 = "a = zeros((size, size), dtype=int)"
array_init_0 = "from array import array; size={}".format(size)
array_init_1 = "a = [array('d', [0])*size for j in range(size)]"
ctyps_init_0 = "from ctypes import c_int; size={}".format(size)
ctypes_init_1 = "a = (c_int * size * size)()"
dp = '''
MOD = int(1e9+7)
for i in range(size):
a[i][0] = 1
for j in range(size):
a[0][i] = 1
for i in range(1, size):
for j in range(1, size):
a[i][j] = (a[i][j] + a[i-1][j] + a[i][j-1]) % MOD
'''
def test(name, init_0, init_1, dp, n=10):
t = timeit.timeit(init_1, setup=init_0, number=n)
print("{} initial time:\t{:.8f}".format(name, t))
t = timeit.timeit(dp, setup=init_0 + '\n' + init_1, number=n)
print("{} calculate time:\t{:.8f}".format(name, t))
test("range", range_init_0, range_init_1, dp)
test("multi", multi_init_0, multi_init_1, dp)
test("numpy", numpy_init_0, numpy_init_1, dp)
test("array", array_init_0, array_init_1, dp)
test("ctypes", ctyps_init_0, ctypes_init_1, dp)
print('------')
numba_init_0 = '''
import numpy as np
size = {}
a = np.zeros((size, size), dtype=np.int32)
'''.format(size)
numba_init_1 = '''
import numba
def dp1(a):
size = len(a)
MOD = int(1e9+7)
for i in range(size):
a[i][0] = 1
for j in range(size):
a[0][i] = 1
for i in range(1, size):
for j in range(1, size):
a[i][j] = (a[i][j] + a[i-1][j] + a[i][j-1]) % MOD
dp_jit = numba.jit('void(i4[:,:])')(dp1)
'''
dp = "dp_jit(a)"
test("numba", numba_init_0, numba_init_1, dp)
结果:
range initial time: 0.56781153
range calculate time: 5.08359793
multi initial time: 0.03682878
multi calculate time: 5.14657282
numpy initial time: 0.00883761
numpy calculate time: 12.15619322
array initial time: 0.02656035
array calculate time: 5.27542352
ctypes initial time: 0.00523795
ctypes calculate time: 7.88469346
------
numba initial time: 2.98394509
numba calculate time: 0.05321887
(此处的Numba初始化时间不包括numpy初始化)
正如我们所看到的,numpy和CTYPE在计算时都比本机列表慢
Numba JIT需要一些时间,但计算时间要短得多
(不要在在线判断平台上使用Python进行2D动态编程!)如果这让您感到震惊,请尝试测量内存消耗。它可能不会大17倍,但肯定会很糟糕。ctypes可能会有所帮助,但肯定不会像numpy看到这个问题那样多。。大到100k?然后我希望你的数组(1)不是正方形的,尽管你的例子是正方形的,或者(2)非常稀疏,因为要跟踪的单元格太多了。我真的认为,如果不知道对数据做了什么,这个问题就无法真正回答。还有一个导入数组,它被限制为1D,但是可以列出数组。将它放入[[0]*size for uuin xrange(size)],或数组('d',[0])中[0](它是类型识别的,因此占用的空间要小得多),可以消除一个循环。@Sebastian:这是一个用于实现的,这个计时代码不起作用:
t1=time.clock()
设置一个局部变量。这就是为什么d
和e
有相同的时间,而e
应该快得多。如果您解决了这个问题(例如starttimer
中的global t1
),您会得到更合理的结果。使用timeit
模块通常更容易。顺便说一句,array
并不是一个公平的比较,因为它实际上并没有生成5000^2个单元格。还要记住,它们做的事情并不相同。例如,尝试更改耳环的一个元素,然后查看结果。@JoeKington我已更改耳环。我想我知道哪里出了问题-/既然您已经做到了,那么可以为array添加导入数组、array.array('d',[0])*大小,而不是[0]*大小。
range initial time: 0.56781153
range calculate time: 5.08359793
multi initial time: 0.03682878
multi calculate time: 5.14657282
numpy initial time: 0.00883761
numpy calculate time: 12.15619322
array initial time: 0.02656035
array calculate time: 5.27542352
ctypes initial time: 0.00523795
ctypes calculate time: 7.88469346
------
numba initial time: 2.98394509
numba calculate time: 0.05321887