fortran 2003 и указатели

Я пишу программу на Фортране. В программе реализованы некоторые численные методы. Скорость программы очень важна. Я решил избавиться от динамических массивов (ускоряет ли это программу?) И столкнулся со следующей проблемой. У меня есть трехмерные массивы (элементы NXxNYxNZ = MAX), где я знаю MAX, но я не знаю соотношение NX / NY / NZ. Это может быть так: 1x1xNZ или как это 2xNYx1 и т. Д. Решение, которое я вижу — использовать указатели. Упрощенный 2D-случай:

program ptrtest
   parameter ( MAX = 50 )    ! I know this number on compile time.
   integer :: NX,NY          ! I will find this numbers on run time.
   real, target :: a(MAX)    ! Static Array
   real, pointer :: b(:,:)
   a = 5
   read(*,*) NX, NY          ! I get NX, NY (NX*NY == MAX)
   b (1:NX, 1:NY) => a       ! I can use b(:,:) <- this is my goal.
end program ptrtest

Этот пример работает, но я боюсь, что такое обновление замедлит работу реальной программы, в которой я использую даже 5d массивы. Является ли это возможным?

Вы не показываете достаточно программы, чтобы по-настоящему комментировать (Вы работаете с a и b одновременно? Вы сразу передаете b в подпрограмму?), Но в целом производительность будет хуже при работе с переменными, которые имеют TARGET или POINTER, потому что некоторые оптимизации могут быть предотвращены. Это будет зависеть от специфики, но выделение выделяемого массива размера (nx, ny) один раз вряд ли будет таким значительным падением производительности по сравнению с чем-то вроде оператора READ, который заполняет nx и ny.   —  person Vasiliy    schedule 18.12.2014

Если вам нужен массив с размерами, определяемыми во время выполнения, я рекомендую использовать выделяемый массив, а не массив указателей, если вам также не нужна дополнительная функция указателя. размещаемые объекты безопаснее. Кроме того, лучше всего решить вашу проблему, а затем определить медленные части, а не гадать с самого начала. Микрооптимизации редко имеют большое значение. Выбор эффективного алгоритма важен.   —  person Vasiliy    schedule 18.12.2014

См. также:  Указатели на шаблонный класс

FWIW Я согласен с другими комментаторами. Но если вы знаете MAX во время компиляции, но не знаете, до времени выполнения _2 _, _ 3_ и nz, вы всегда можете использовать проверенный (для которого понимается «старомодный») подход использования одномерного массива ( из MAX элементов) и арифметические операции с собственным индексом. Если вы рассматриваете этот подход, внимательно изучите наблюдения @ M.S.B. по оптимизации.   —  person Vasiliy    schedule 18.12.2014

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Vasiliy

    Вы говорите, что скорость программы важна, поэтому старый стиль Fortran даст вам лучшее:

    • выделить одномерный массив размером MAX
    • pass относится к подпрограмме, а также _2 _, _ 3_ и 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
    • Измерьте физически ваш 2D-массив так, чтобы размер ведущего измерения был кратен 32 байтам. Для реального * 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 позволяет избежать наложения имен указателей.

    Ссылки на псевдонимы указателей:

    так что старый стиль Fortran даст вам лучшее Покажите нам числа; без данных этот «ответ» — мнение. person Vasiliy; 18.12.2014

    Это не мнение. Посмотрите на параметр -fno-alias компиляторов C, чтобы получить дополнительные объяснения. Как я уже сказал: (в отличие от C, стандарт Fortran предполагает, что аргументы массива подпрограмм не перекрываются). Псевдонимы указателей — это хорошо известная проблема для компиляторов, и она отсутствовала в Фортране до того, как они представили указатели. Видеть person Vasiliy; 18.12.2014

    Я тоже хотел бы увидеть реальные цифры. person Vasiliy; 19.12.2014

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: