Вы говорите, что скорость работы программы имеет важное значение, так старый стиль Fortran даст вам лучшее:
- выделить 1D массив размера
MAX
- прохода к подпрограмме, а также
NX
, NY
, и NZ
. Это позволит избежать указателя , который приведет к потере производительности (в отличие от C, стандарт Fortran предполагает, что аргументы массива подпрограмм не перекрываются, см. this post).
Например:
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
- Измерьте физически свой 2D-массив таким образом, чтобы размер ведущего измерения был кратным 32 байтам. Для реального * 4 вам нужно несколько из восьми элементов.
- Скажи компилятор, что каждый столбец правильно выровненный с помощью
!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 трюк избегает поворота ter aliasing.
Ссылки на указатель ступенчатости:
Вы не показывают достаточно программу, чтобы действительно комментарий (Вы работаете одновременно с a и b? y передавая b подпрограмме?), но в целом производительность будет хуже при работе с переменными, которые имеют атрибут TARGET или POINTER, поскольку некоторые оптимизации могут быть предотвращены. Это будет зависеть от специфики, но выделение выделяемого массива размера (nx, ny) один раз вряд ли будет таким значительным, как и показатель READ, который заполняет nx и ny. – IanH
Если вам нужен массив с определенными размерами времени выполнения, я рекомендую использовать выделяемый массив, а не массив указателей, если вам не нужна дополнительная функция указателя. ассигнования более безопасны. Кроме того, лучше всего решить вашу проблему, а затем определить медленные части, а не догадываться в начале. Микро-оптимизации редко имеют большое значение. Важным является выбор эффективного алгоритма. –
FWIW Я согласен с другими комментаторами. Но если вы знаете 'MAX' во время компиляции, но нет, то до времени выполнения,' nx', 'ny' и' nz' вы всегда можете использовать проверенные и проверенные (для которых нужно понимать «старомодные»,) подход использования 1D-массива (элементов 'MAX') и арифметики с индексом roll-your-own. Если учесть этот подход, внимательно рассмотрите замечания @ M.S.B по оптимизации. –