【问题标题】:numpy array size vs. speed of concatenationnumpy 数组大小与连接速度
【发布时间】:2016-04-17 06:51:12
【问题描述】:

我将数据连接到一个 numpy 数组,如下所示:

xdata_test = np.concatenate((xdata_test,additional_X))

这已经完成了一千次。数组的dtype为float32,其大小如下所示:

xdata_test.shape   :  (x1,40,24,24)        (x1 : [500~10500])   
additional_X.shape :  (x2,40,24,24)        (x2 : [0 ~ 500])

问题在于,当x1 大于~2000-3000 时,连接所需的时间会更长。

下图绘制了连接时间与x2 维度大小的关系:

这是内存问题还是 numpy 的基本特征?

【问题讨论】:

    标签: python performance numpy


    【解决方案1】:

    如果您事先有要连接的数组,我建议您创建一个具有总形状的新数组并用小数组填充它而不是连接,因为每个连接操作都需要将整个数据复制到一个新的连续的内存空间。

    • 首先,计算第一个轴的总大小:

      max_x = 0
      for arr in list_of_arrays:
          max_x += arr.shape[0]
      
    • 其次,创建结束容器:

      final_data = np.empty((max_x,) + xdata_test.shape[1:], dtype=xdata_test.dtype)
      

      相当于(max_x, 40, 24, 24),但是是动态类型的。

    • 最后,填充numpy数组:

      curr_x = 0
      for arr in list_of_arrays:
          final_data[curr_x:curr_x+arr.shape[0]] = arr
          curr_x += arr.shape[0]
      

    上面的循环,将每个数组复制到更大数组的先前定义的列/行。

    通过这样做,每个N 数组将被复制到确切的最终目的地,而不是为每个连接创建临时数组。

    【讨论】:

      【解决方案2】:

      据我了解 numpy,所有 stackconcatenate 函数都不是非常有效。并且有充分的理由,因为 numpy 试图保持数组内存连续以提高效率(请参阅this link about contiguous arrays in numpy

      这意味着每个连接操作都必须每次都复制整个数据。当我需要将一堆元素连接在一起时,我倾向于这样做:

      l = []
      for additional_X in ...:
          l.append(addiional_X)
      xdata_test = np.concatenate(l)
      

      这样,移动整个数据的昂贵操作只需执行一次。

      NB : 会对为您带来的速度改进感兴趣。

      【讨论】:

      • 是的,整个列表的一次连接操作比重复的二进制操作要好得多。 concatenate 创建一个大小合适的空结果数组,然后从每个源复制数据。一次性连接会减少副本。
      猜你喜欢
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 2015-08-07
      相关资源
      最近更新 更多