我需要对一大堆数字进行一些计算。
对于典型的数组,array.array或numpy.array能否显着提升性能?
我不需要对数组进行复杂的操作,我只需要能够访问和修改值,
e.g。
import numpy
x = numpy.array([0] * 1000000)
for i in range(1,len(x)):
x[i] = x[i-1] + i
所以我真的不需要连接,切片等等。
此外,如果我尝试分配不适合C long的值,则看起来像数组会抛出错误:
import numpy
a = numpy.array([0])
a[0] += 1232234234234324353453453
print(a)
在控制台上我得到:
a[0] += 1232234234234324353453453
OverflowError: Python int too large to convert to C long
是否有一个变量的数组允许我放入无界的Python整数? 或者这样做会在一开始就消除阵列的重点?
答案 0 :(得分:12)
首先需要了解数组和列表之间的区别。
数组是一个连续的内存块,由某种类型的元素组成(例如整数)。
创建数组后,无法更改数组的大小 因此,阵列中的每个整数元素具有固定大小 ,例如, 4个字节。
另一方面,列表仅仅是一个"数组" 地址(也有固定大小)。
然后每个元素在内存中保存 else 的地址,这是您想要使用的实际整数。当然,此整数的大小与数组的大小无关。因此,您始终可以创建一个新的(更大的)整数和"替换"旧的,不影响数组的大小,只保存整数的地址。
当然,列表的这种方便是有代价的:对整数执行算术现在需要对数组进行内存访问,加对整数本身的内存访问,加分配更多内存所需的时间(如果需要),加删除旧整数所需的时间(如果需要)。所以是的,它可能会更慢,所以你必须小心你对数组中每个整数所做的事情。
答案 1 :(得分:8)
你的第一个例子可能是加速。 Python循环和对numpy数组中各个项的访问速度很慢。改为使用矢量化操作:
import numpy as np
x = np.arange(1000000).cumsum()
你可以将无界的Python整数放到numpy数组中:
a = np.array([0], dtype=object)
a[0] += 1232234234234324353453453
与固定大小的C整数相比,算术运算在这种情况下会更慢。
答案 2 :(得分:2)
对于大多数用途,列表很有用。例如,有时使用numpy数组可能更方便。
a=[1,2,3,4,5,6,7,8,9,10]
b=[5,8,9]
考虑列表'a',如果要访问列表'b'中给出的离散索引列表中的元素 写作
a[b]
无效。
但是当你将它们用作数组时,你可以简单地写
a[b]
将输出作为数组([6,9,10])。
答案 3 :(得分:1)
array.array或numpy.array提供了显着的性能提升 典型的数组?
我尝试使用以下代码对此进行测试:
import timeit, math, array
from functools import partial
import numpy as np
# from the question
def calc1(x):
for i in range(1,len(x)):
x[i] = x[i-1] + 1
# a floating point operation
def calc2(x):
for i in range(0,len(x)):
x[i] = math.sin(i)
L = int(1e5)
# np
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20)))
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20)))
# np but with vectorized form
vfunc = np.vectorize(math.sin)
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20)))
# with list
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20)))
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20)))
# with array
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20)))
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20)))
结果是列表在这里执行得最快(Python 3.3,NumPy 1.8):
np 1: 2.14277 s
np 2: 0.77008 s
np 2 vectorized: 0.44117 s
list 1: 0.29795 s
list 2: 0.66529 s
array 1: 0.66134 s
array 2: 0.88299 s
这似乎违反直觉。对于这些简单的示例,使用numpy
或array
优于list
似乎没有任何优势。
答案 4 :(得分:0)
对于典型的数组,array.array或numpy.array能否显着提升性能?
它可以,取决于你正在做什么。
或者这样做会不会带走阵列的第一位?
差不多,是的。
答案 5 :(得分:0)
使用a=numpy.array(number_of_elements, dtype=numpy.int64)
,它应该为您提供64位整数数组。这些可以存储-2 ^ 63和(2 ^ 63)-1之间的任何整数(大约在-10 ^ 19和10 ^ 19之间),这通常是绰绰有余。
答案 6 :(得分:0)
致OP:对于您的用例,请使用列表。
考虑到健壮性和速度,我的使用时间规则:
列表 :(最可靠,易变案例最快) 例如当您的列表像物理模拟中一样不断变化时。当您从头开始“创建”数据时,实际上这可能是无法预测的。
np.arrary :(较不健壮,对于线性代数和数据后处理最快) 例如当您进行“后期处理”时,您已经通过传感器或模拟收集的数据集;执行可以矢量化的操作。