你说程序速度很重要,所以老式的 Fortran 会给你最好的:
- 分配一个大小为一维的数组
MAX
- pass 是子程序以及
NX
,NY
和NZ
. 这将避免指针间接导致性能损失(与 C 不同,Fortran 标准假定子例程数组参数不重叠,请参阅这篇文章)。
例如:
program noptrtest
implicit none
integer, parameter :: MAX = 50 ! I know this number on compile time.
integer :: NX,NY ! I will find this numbers on run time.
real :: a(MAX) ! Static Array
read(*,*) NX, NY ! I get NX, NY (NX*NY == MAX)
if (NX*NY /= MAX) then
stop 'NX*NY /= MAX'
endif
call run(a,NX,NY)
end program noptrtest
subroutine run(b,NX,NY)
integer :: NX,NY
real :: b(NX,NY)
integer :: i,j
do j=1,NY
do i=1,NX
! use b(i,j) here
enddo
enddo
end
如果性能真的很重要,这里还有一些其他有用的技巧:
- 告诉你的编译器在 32 字节边界上对齐数组(使用 ifort,使用
!DIR$ ATTRIBUTES ALIGN : 32
指令
- 对二维数组进行物理尺寸标注,使前导尺寸的大小是 32 字节的倍数。对于 real*4,您需要 8 个元素的倍数。
!DIR$ VECTOR ALIGNED
使用指令告诉编译器每一列都正确对齐
例如:
program noptrtest
implicit none
integer, parameter :: real_kind = 4
integer, parameter :: MAX = 50 ! I know this number on compile time.
integer, parameter :: MAXDIM = MAX*(32/real_kind) ! Max possible dimension required
integer :: NX,NY, NX_MOD ! I will find this numbers on run time.
real(real_kind) :: a(MAXDIM) ! Static Array
!DIR$ ATTRIBUTES ALIGN : 32 :: a
read(*,*) NX, NY ! I get NX, NY (NX*NY == MAX)
if (NX*NY /= MAX) then
stop 'NX*NY /= MAX'
endif
if (mod(NX,real_kind) == 0) then
NX_MOD = NX
else
NX_MOD = ((NX/real_kind)+1)*real_kind
endif
call run(a,NX_MOD,NX,NY)
end program noptrtest
subroutine run(b,NX_MOD,NX,NY)
integer :: NX_MOD,NX,NY
real :: b(NX_MOD,NY)
integer :: i,j
do j=1,NY
!DIR$ VECTOR ALIGNED
do i=1,NX
! use b(i,j) here
enddo
enddo
end
编辑
这种老式的 Fortran技巧避免了指针别名。
关于指针别名的参考: