如何提高numpy数组的效率?

8 投票
3 回答
5053 浏览
提问于 2025-04-16 02:16

我刚开始接触numpy,听说它在内存访问方面的效率跟C语言差不多,这让我很惊讶。我想亲自看看numpy的ndarrays和普通的Python列表有什么区别,于是我做了个简单的时间测试,分别用numpy和普通列表做了一些相同的简单任务。结果果然,numpy在分配数组和进行数学运算方面比普通列表快了很多倍。不过,有一段代码在两个测试中是完全相同的,使用普通列表时大约只花了1/8秒,而用numpy却花了超过2.5秒:

file = open('timing.log','w')
for num in a2:
    if num % 1000 == 0:
        file.write("Multiple of 1000!\r\n")

file.close()

有没有人知道这是为什么?我是否应该使用其他语法来进行这样的操作,以更好地利用ndarray的功能?

谢谢...

补充说明:为了回应Wayne的评论... 我多次测试了这两个,顺序也不一样,每次结果几乎都一样,所以我怀疑不是其他进程的问题。我把

start = time()
放在文件顶部,在numpy导入之后,然后在文件中有像
print 'Time after traversal:\t',(time() - start)
这样的语句。

3 个回答

5

对numpy数组进行逐个元素访问会非常慢。建议使用向量操作:

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' '
>    sum(1 for i in a2 if i % 1000 == 0)'
10 loops, best of 3: 1.53 sec per loop

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' '
>    (a2 % 1000 == 0).sum()'
10 loops, best of 3: 22.6 msec per loop

$ python -mtimeit -s 'import numpy as np; a2=    range(10**6)' '
>    sum(1 for i in a2 if i % 1000 == 0)'
10 loops, best of 3: 90.9 msec per loop
6

我并不惊讶你用的代码片段在性能上NumPy表现得不如Python自带的功能。NumPy的一个重要优势就是它能避免使用循环,而是通过索引直接访问数组,这样可以提高性能。

在NumPy中,通常会这样做:

A = NP.random.randint(10, 100, 100).reshape(10, 10)
w = A[A % 2 == 0]
NP.save("test_file.npy", w)
10

a2 是一个 NumPy 数组,对吧?如果它在 NumPy 中运行得很慢(假如其他进程的活动不是原因,就像 Wayne Werner 提到的那样),一个可能的原因是你在用 Python 的循环来遍历这个数组。在每一步循环中,Python 都需要从 NumPy 数组中取出一个值,并把它转换成 Python 的整数,这个过程其实并不快。

NumPy 在你能对整个数组进行操作时效果会更好。在你的情况下,有一个选择(可能不是最快的)是

file.write("Multiple of 1000!\r\n" * (a2 % 1000 == 0).sum())

你可以试着把这个和纯 Python 的做法进行比较,

file.write("Multiple of 1000!\r\n" * sum(filter(lambda i: i % 1000 == 0, a2)))

或者

file.write("Multiple of 1000!\r\n" * sum(1 for i in a2 if i % 1000 == 0))

撰写回答