Numpy按Fortran顺序reshape速度慢原因及无拷贝转置方案问询
NumPy三维C连续数组转Fortran连续视图相关问题解答
两种reshape写法的速度差异成因
np.reshape的order参数会同时作用于从原数组取值和向输出数组写入两个阶段:
- 直接对原数组调用
np.reshape(a, [3000,2000,1000], order='F')时,NumPy需要按Fortran顺序从原C连续数组中取值重排,这一步会触发全量数据拷贝,你测试中的24秒就是拷贝约24GB(100020003000*4字节)数据的耗时,最终得到的c是独立新数组而非视图。 - 先调用
a.ravel()再reshape的写法中,ravel()默认返回C连续的一维展平视图,此时再用order='F'reshape,仅需要修改数组的shape和stride元属性,不需要拷贝任何数据,耗时只有微秒级,得到的b是原数组的共享内存视图。
零拷贝转Fortran顺序视图的方案
你此前对三维数组不支持转置的认知是误区,NumPy任意维度数组都支持.T操作,a.T就是最简单的零拷贝Fortran连续视图:它完全通过修改stride实现维度反转,不会触发数据拷贝,得到的数组天然满足F连续的要求,是该场景下的最优解。
注意np.asfortranarray只有在要求输出和输入形状一致时才会强制生成拷贝,如果你可以接受维度反转后的形状,直接用.T即可。
f2py自动处理数组顺序的方法
f2py本身就支持自动适配输入数组的内存布局,不需要你手动转置:
- 你只需要把Fortran子程序里的数组维度顺序和NumPy里的声明反过来即可,比如NumPy中数组维度是
(x,y,z),Fortran里声明为(z,y,x),f2py会自动适配内存布局,不会产生额外拷贝。 - 也可以在编译f2py模块时指定
intent(in, out, inplace)等属性,调用时不需要手动做转置操作,f2py会自动完成内存布局适配。
验证代码参考
import numpy as np a = np.empty([1000,2000,3000],dtype=np.float32) # 方案1:先ravel再reshape b = np.reshape(a.ravel(),[3000,2000,1000],order='F') print(np.shares_memory(a, b)) # 输出True # 方案2:直接转置(更简便) d = a.T print(np.shares_memory(a, d)) # 输出True print(d.flags.f_contiguous) # 输出True # 直接reshape方案 c = np.reshape(a,[3000,2000,1000],order='F') print(np.shares_memory(a, c)) # 输出False
内容的提问来源于stack exchange,提问作者L. Robison
相关产品推荐
相关产品推荐

