【问题标题】:Why are for loops quicker than numpy for 2D array multiplication为什么对于二维数组乘法,for 循环比 numpy 快
【发布时间】:2015-01-21 11:05:22
【问题描述】:

考虑以下两个函数,它们基本上将一个小序列中的每个数字与一个大序列中的每个数字相乘以构建一个二维数组,然后将数组中的所有值加倍。 noloop() 使用 2D numpy 数组的直接乘法并返回结果,而 loop() 使用 for 循环遍历 arr1 并逐渐构建输出数组。

import numpy as np

arr1 = np.random.rand(100, 1)
arr2 = np.random.rand(1, 100000)

def noloop():
    return (arr1*arr2)*2

def loop():
    out = np.empty((arr1.size, arr2.size))
    for i in range(arr1.size):
        tmp = (arr1[i]*arr2)*2
        out[i] = tmp.reshape(tmp.size)
    return out

我预计 noloop 即使对于少量迭代也会更快,但对于上述数组大小,loop 实际上更快:

>>> %timeit noloop()
10 loops, best of 3: 64.7 ms per loop
>>> %timeit loop()
10 loops, best of 3: 41.6 ms per loop

有趣的是,如果我在这两个函数中删除 *2noloop 会更快,但只是稍微:

>>> %timeit noloop()
10 loops, best of 3: 29.4 ms per loop
>>> %timeit loop()
10 loops, best of 3: 34.4 ms per loop

对这些结果是否有很好的解释,是否有明显更快的方法来执行相同的任务?

【问题讨论】:

  • 我得到noloop()loop() 快(约15%),无论如何...
  • 我在 python2 和 python3 上也得到了相反的结果。
  • 我得到 loop 更快,正如 OP 所建议的那样(在我的机器中提高了 28%)。 Python 3.4.1 | Anaconda 2.1.0,IPython 2.2.0
  • OP 值来自 Spyder,即 QT IPython 控制台。我使用 Spyder 之外的 QT IPython 控制台得到了相同的结果。奇怪的是,在普通的 IPython 控制台中,noloop() 似乎和以前一样长(60-70 毫秒),而 loop()noloop() 长了几毫秒,即比 QT 控制台慢得多。
  • 这里也一样,noloop() 在我的机器上快了约 10%。

标签: python for-loop numpy


【解决方案1】:

我无法重现您的结果,但我确实发现使用 numpy.multiply 可以显着提高速度(2 倍)。通过使用out 参数,您可以利用内存已分配的事实并消除将tmp 复制到out

def out_loop():
    out = np.empty((arr1.size, arr2.size))
    for i in range(arr1.size):
        np.multiply(arr1[i], arr2, out=out[i].reshape((1, arr2.size)))
        out[i] *= 2
    return out

我的机器上的结果:

In [32]: %timeit out_loop()
100 loops, best of 3: 17.7 ms per loop

In [33]: %timeit loop()
10 loops, best of 3: 28.3 ms per loop

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2018-05-29
    • 2021-10-01
    • 2021-08-10
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多