Fortran派生类型数组中%操作符的工作机制及内存副本疑问
Fortran中派生类型数组上%操作符的工作机制
我想了解Fortran中%操作符在派生类型数组上的工作机制,为此编写了一段重载+运算符的程序,现在有个疑问:在add_my_type_vec函数中,执行res%r1 = a%r1 + b%r1这类语句时,是否会先创建仅包含a%r1和b%r1的实型数组副本,再进行求和并赋值给res%r1?我猜测实际机制更为复杂。
module my_mod implicit none type :: my_type real :: r1 , r2 integer :: i1, i2 end type my_type interface operator(+) module procedure add_my_type_vec, add_my_type end interface contains function add_my_type_vec(a,b) result(res) type(my_type), dimension(:),intent(in) :: a, b type(my_type), dimension(size(a)) :: res res%r1 = a%r1 + b%r1 res%r2 = a%r2 + b%r2 res%i1 = a%i1 + b%i1 res%i2 = a%i2 + b%i2 end function add_my_type_vec function add_my_type(a,b) result(res) type(my_type), intent(in) :: a, b type(my_type) :: res res%r1 = a%r1 + b%r1 res%r2 = a%r2 + b%r2 res%i1 = a%i1 + b%i1 res%i2 = a%i2 + b%i2 end function add_my_type end module my_mod program my_pgm use my_mod implicit none type(my_type),allocatable, dimension(:) :: my_vec1, my_vec2, my_vec3 write(*,*) "Sum on type : ", my_type(1.0, 2.0, 1, 2) + my_type(1.0, 2.0, 1, 2) allocate(my_vec1(1000), my_vec2(1000), my_vec3(1000)) my_vec1 = my_type(1.0, 2.0, 1, 2) my_vec2 = my_type(1.0, 2.0, 1, 2) my_vec3 = my_vec1 + my_vec2 write(*,*) "Sum on vec of type : ", my_vec3(123) end program my_pgm
解答
不会创建临时数组副本(至少现代Fortran编译器在优化模式下不会)。
当对派生类型数组使用%访问其成员时,比如a%r1,编译器会直接生成指向该成员数组的内存引用——因为派生类型数组的存储是按列主序连续排布的:每个元素的r1、r2、i1、i2依次存放,整个数组的所有r1成员会形成一块连续的内存区域,布局和独立的实型数组完全一致。
执行res%r1 = a%r1 + b%r1时,编译器会直接遍历a%r1和b%r1的内存地址,逐元素计算求和并写入res%r1的对应位置,全程不需要额外复制整个成员数组。
这种行为是Fortran对派生类型数组的“数组段”优化特性,编译器会识别出这类成员访问的连续内存属性,直接生成高效的内存操作指令,避免不必要的内存开销。
当然,如果是在未开启优化的调试模式下,部分编译器可能会生成临时数组的代码,但生产环境下的优化编译(比如-O2或更高)会完全消除这类冗余操作。
内容的提问来源于stack exchange,提问作者Stef1611
相关产品推荐
相关产品推荐

