19

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

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

当我尝试使用 %timeit 测量时间时。它在微秒内完成了这个转置,(远小于复制我所拥有的 (112x1024x1024) 数组所需的时间。

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

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

更新

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

感谢所有的答案。

4

3 回答 3

21

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

于 2013-10-20T15:49:59.957 回答
6

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

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

于 2013-10-20T17:41:52.017 回答
0

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

a = np.ascontiguousarray(a.transpose())
于 2022-01-26T20:29:36.117 回答