【问题标题】:Is it possible to speed up calculation of very large arrays in numpy?是否可以加快 numpy 中非常大的数组的计算速度?
【发布时间】:2020-03-02 17:43:08
【问题描述】:

我环顾四周,但找不到确切的答案。

我有几个 1200x2000 的矩阵,我想以某种方式保存它们,以便以后在某种循环中读取它们。当我想使用下面的方法保存 100 个这样的矩阵时,这个过程真的很快。但是如果我想节省1000,每次迭代所需的时间会变得很长。

这是问题的一个例子(这里的矩阵只有 1,因为问题已经出现在这个简单的案例中):

reps = 1000
ret100 = np.zeros([1200, 2000, reps])
for k in range(reps):
    ret100[:,:,k] = 1
    print(k)

与相同的事物相比,但 reps=100:

reps = 100
ret100 = np.zeros([1200, 2000, reps])
for k in range(reps):
    ret100[:,:,k] = 1
    print(k)

我有两个问题:

  1. 为什么与 100 相比,当 reps = 1000 时,上述迭代中的每个步骤需要更长的时间?这是预期的行为吗?
  2. 有没有比上面介绍的更好的方法来存储一堆矩阵?

【问题讨论】:

  • 嗨@Thiago。因为你在运行解释器,Python 每次都必须解释循环内的代码,这需要大量的处理。一般来说,要加速大型循环,您需要使用静态类型的编译语言。当您使用 Numpy 的函数对数组的所有元素执行类似的操作时,Numpy 运行良好,允许 numpy 处理循环,例如ret100=ret100+1。至于您的第二个问题,我建议您对代码进行分析或计时并单独发布。
  • @Thiago,一般来说,尽量避免在 Numpy 中使用 python 循环。
  • @Jake Stevens-Haas “Python 每次都必须解释循环内的代码”我认为这不是真的。在 Python 中运行代码之前(例如,循环),它被编译为字节码,然后在该代码后续执行时重新使用。见docs.python.org/3/library/dis.html
  • 请提供一个更好的例子。现在你的代码只是np.ones((1200, 2000, reps))。请解释你真正想要什么,并证明你的循环迭代很慢。
  • 您能否添加性能数字,以便我们看到 100 和 1000 之间的差异?

标签: python performance numpy multidimensional-array


【解决方案1】:

您正在以一种非常低效的方式访问内存中的单元格。 这是一个简单的测试,看看为什么:

a = np.zeros([1200, 2000, 100])
a[1,:,:] = 1 # time: 97.3 µs
a[:,1,:] = 1 # time: 345 µs
a[:,:,1] = 1 # time: 16 ms

对第一个维度的值的访问模式效率不高。这是因为与其他维度相反,最后一维的单元格连续存储在内存中。以非连续方式访问内存通常要慢得多(步幅越大,越慢)。

所以考虑像这样交换维度的顺序:

reps = 100
ret100 = np.zeros([reps, 2000, 1200])
for k in range(reps):
    ret100[k,:,:] = 1
    print(k)

这在我的机器上快了 10 倍以上。在更大的阵列上加速甚至更大(例如,将 reps 设置为 1000)。

【讨论】:

  • 非常感谢!
【解决方案2】:

我不确定这是否是你想要的,如果我误解了,请纠正我。

import numpy as np
reps = 1000
ret100 = np.zeros([1200, 2000, reps])
ret100[:,:,0:reps] = 1

【讨论】:

  • 0:reps 只是:
  • 整个事情就相当于np.ones(...)吧?
  • 是的,我对问题添加了评论。真的不清楚OP在问什么。
猜你喜欢
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-30
  • 1970-01-01
  • 2013-11-08
  • 2016-12-20
相关资源
最近更新 更多