【问题标题】:Is numpy.transpose reordering data in memory?numpy.transpose 是否在内存中重新排序数据?
【发布时间】:2013-10-29 01:14:26
【问题描述】:

为了加快 np.std、np.sum 等函数沿 n 维巨大 numpy 数组的轴执行,建议沿最后一个轴应用。

当我这样做时, np.transpose 将我想要操作的轴旋转到最后一个轴。是真的重新洗牌内存中的数据,还是只是改变轴的寻址方式?

当我尝试使用 %timeit 测量时间时。它在微秒内完成了这个转置,(比我复制 (112x1024x1024) 数组所需的时间要短得多。

如果它实际上并没有对内存中的数据进行重新排序而只是更改了地址,那么当应用于新旋转的最后一个轴时,它是否仍会加快 np.sum 或 np.std 的速度?

当我尝试测量它时,我似乎确实加快了速度。但我不明白怎么做。

更新

转置似乎并没有真正加快速度。最快的轴在 C 排序时是最后一个,而在 Fortran 排序时是第一个。因此,在应用 np.sum 或 np.std 之前进行转置是没有意义的。 对于我的特定代码,我通过在数组创建期间给出 order='FORTRAN' 解决了这个问题。这使得第一个轴最快。

感谢大家的回答。

【问题讨论】:

    标签: python arrays optimization numpy


    【解决方案1】:

    Transpose 只是改变了strides,它不会触及实际的数组。我认为建议沿最终轴使用sum 等的原因(顺便说一句,我想查看其来源)是当数组是 C 排序时,沿最终轴行走会保留参考的位置.转置后不会出现这种情况,因为转置后的数组将是 Fortran 排序的。

    【讨论】:

    • 哦,好的。那么这样说是否正确,为了提高沿轴的速度,首先将其转置然后应用总和是没有意义的?
    • @indiajoe:您应该进行测量以找出答案(也许 NumPy 中存在一些我不知道的优化),但如果它导致显着的速度差异,我会感到非常惊讶。跨度>
    • @indiajoe,测量。我唯一能想象的是,一些临时数组恰好有一个更有效的布局。但我不会真的期待它,虽然更可能是在旧的 numpy
    • @larsmans,@seberg :我现在尝试测量。看起来,最快的轴总是保持不变。无论你如何转置。在 C 排序时,最后一个轴是最快的,而在 Fortran 排序时,第一个轴是最快的。所以,我想我可以有把握地得出结论,为了加快手术速度,这些都没有意义。当我创建数组本身时,应该给 order= 参数进行优化。谢谢
    【解决方案2】:

    为了详细说明 larsman 的回答,这里有一些时间安排:

    # normal C (row-major) order array
    >>> %%timeit a = np.random.randn(500, 400)
    >>> np.sum(a, axis=1)
    1000 loops, best of 3: 272 us per loop
    
    # transposing and summing along the first axis makes no real difference 
    # to performance
    >>> %%timeit a = np.random.randn(500, 400)
    >>> np.sum(a.T, axis=0)
    1000 loops, best of 3: 269 us per loop
    
    # however, converting to Fortran (column-major) order does improve speed...
    >>> %%timeit a = np.asfortranarray(np.random.randn(500,400))
    >>> np.sum(a, axis=1)
    10000 loops, best of 3: 114 us per loop
    
    # ... but only if you don't count the conversion in the timed operations
    >>> %%timeit a = np.random.randn(500, 400)
    >>> np.sum(np.asfortranarray(a), axis=1)
    1000 loops, best of 3: 599 us per loop
    

    总而言之,如果您要对列应用大量操作,将数组转换为 Fortran 顺序可能是有意义的,但转换本身的成本很高,而且对于单个操作几乎肯定不值得。

    【讨论】:

    • 谢谢。这就是我最后所做的。我在数组本身的生成时将数组转换为 fortran 顺序。
    【解决方案3】:

    您可以使用np.ascontinguousarray 强制进行物理重组。比如……

    a = np.ascontiguousarray(a.transpose())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 2021-12-02
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多