python - 为什么 numpy 数组看起来并不比标准 python 列表快多少?

标签 python arrays numpy parallel-processing

据我所知,numpy 数组可以比 python 列表更快地处理操作,因为它们是以并行方式而不是迭代方式处理的。我试图对此进行测试以获得乐趣,但我没有看到太大的不同。

我的测试有问题吗?区别只对比我使用的数组大得多的数组有影响吗?我确保在每个函数中创建一个 python 列表和 numpy 数组,以消除创建一个与另一个可能产生的差异,但时间增量似乎可以忽略不计。这是我的代码:

我的最终输出是 numpy 函数:6.534756324786595s,列表函数:6.559365831783256s

import timeit
import numpy as np

a_setup = 'import timeit; import numpy as np'

std_fx = '''
def operate_on_std_array():
    std_arr = list(range(0,1000000))
    np_arr = np.asarray(std_arr)
    for index,elem in enumerate(std_arr):
        std_arr[index] = (elem**20)*63134
    return std_arr
'''
parallel_fx = '''
def operate_on_np_arr():
    std_arr = list(range(0,1000000))
    np_arr = np.asarray(std_arr)
    np_arr = (np_arr**20)*63134
    return np_arr
'''

def operate_on_std_array():
    std_arr = list(range(0,1000000))
    np_arr = np.asarray(std_arr)
    for index,elem in enumerate(std_arr):
        std_arr[index] = (elem**20)*63134
    return std_arr

def operate_on_np_arr():
    std_arr = list(range(0,1000000))
    np_arr = np.asarray(std_arr)
    np_arr = (np_arr**20)*63134
    return np_arr


print('std',timeit.timeit(setup = a_setup, stmt = std_fx, number = 80000000))
print('par',timeit.timeit(setup = a_setup, stmt = parallel_fx, number = 80000000))



#operate_on_np_arr()
#operate_on_std_array()

最佳答案

The timeit docs here显示您传入的语句应该执行某些操作,但您传入的语句只是定义函数。我当时认为在 100 万长度的数组上进行 80000000 次试验应该花费更长的时间。

您在测试中遇到的其他问题:

  • np_arr = (np_arr**20)*63134 可能会创建 np_arr 的副本,但您的 Python 等效列表只会改变现有数组。
  • Numpy 数学不同于 Python 数学。 Python 中的 100**20 返回一个巨大的数字,因为 Python 有无限长度的整数,但 Numpy 使用 C 风格的定长整数会溢出。 (通常,当您使用 Numpy 时,您必须想象在 C 中执行该操作,因为其他不直观的事情可能适用,例如未初始化数组中的垃圾。)

这是一个测试,我对两者都进行了修改,每次乘以然后除以 31,这样值就不会随时间变化或溢出:

import numpy as np
import timeit

std_arr = list(range(0,100000))
np_arr = np.array(std_arr)
np_arr_vec = np.vectorize(lambda n: (n * 31) / 31)

def operate_on_std_array():
    for index,elem in enumerate(std_arr):
        std_arr[index] = elem * 31
        std_arr[index] = elem / 31
    return std_arr

def operate_on_np_arr():
    np_arr_vec(np_arr)
    return np_arr


import time
def test_time(f):
    count = 100
    start = time.time()
    for i in range(count):
        f()
    dur = time.time() - start
    return dur

print(test_time(operate_on_std_array))
print(test_time(operate_on_np_arr))

结果:

3.0798873901367188 # standard array time
2.221336841583252 # np array time

编辑:正如@user2357112 所指出的,正确的 Numpy 方法是这样的:

def operate_on_np_arr():
    global np_arr
    np_arr *= 31
    np_arr //= 31 # integer division, not double
    return np_arr

让它变得更快。我看到 0.1248 秒。

关于python - 为什么 numpy 数组看起来并不比标准 python 列表快多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49758589/

相关文章:

Python SequenceMatcher 开销 - 100% 的 CPU 使用率和非常缓慢的处理

python - 了解 Python 中的 UnboundLocalError

c - C中数组的理想数据类型

python - 刚性转换 - Python - 加速

python - Pandas 迭代更新列值

Python 3.6.1 - Numpy.power 返回正 int 数的立方幂的负值

python - 如何在 matplotlib 中绘制受数据点限制的网格

python - Python中根据唯一键将列中的类别转换为编码为1或0的多列

javascript - JavaScript 数组元素只不过是数组对象属性吗?

c++ - 为什么派生类不能在数组中工作? (C++)