numpy.transpose是否在内存中重新排序数据?

时间:2013-10-20 15:46:03

标签: python arrays optimization numpy

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

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

当我尝试使用%timeit测量时间时。它在微秒内完成了这个转置(比复制我所拥有的(112x1024x1024)阵列所需的时间小得多。

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

当我试图测量它时,我似乎确实加快了速度。但我不明白如何。

更新

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

感谢所有答案。

2 个答案:

答案 0 :(得分:16)

转置只是更改strides,它不会触及实际的数组。我认为推荐sum等沿着最终轴的原因(我希望看到它的来源,顺便说一句。)是当一个数组是C顺序时,沿着最后一个轴行走会保留局部性参考。转置后不会出现这种情况,因为转置后的数组将是Fortran排序的。

答案 1 :(得分:3)

详细说明了拉斯曼的回答,这里有一些时间:

# 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顺序可能是有意义的,但转换本身成本高昂,几乎肯定不值得单个操作。 / p>