Процедуры с привязкой к типу полиморфных компонентов производных типов

Я пишу код моделирования (почти) с нуля и хочу использовать функции ООП из фортрана, чтобы упростить его обслуживание. На семинаре по Фортрану я узнал, что нужно быть осторожным при использовании функций ООП в критически важных для производительности частях кода.

Моим наивным первым подходом (игнорируя предупреждение) был бы следующий фрагмент. Фоном является расчет энергии системы, для которой нужен потенциал взаимодействия. Для этого потенциала я использую абстрактный тип (потенциал). Затем все пользователи могут добавлять свои собственные потенциалы в качестве расширений и определять ключевое слово, которое используется для выделения их потенциала. Расчет энергии в основной программе не меняется.

module system_mod
implicit none

  type, abstract :: potential
  contains
    procedure(init), deferred :: init
    procedure(eval), deferred :: eval
  end type

  type, extends(potential) :: my_potential
    ! some parameters
  contains
    procedure :: init => init_my_potential 
    procedure :: eval => eval_my_potential
  end type 

  ! omitted: other extensions of 'potential'
  ! and abstract interface of potential

  type :: system
    ! some components
    class(potential), allocatable :: pair_potential
  contains
    procedure :: init ! subroutine, which is used to allocate pair_potential depending on a passed keyword
  end type

contains 

  ! implementation of all routines

end module system_mod

program main
use system_mod, only: potential, my_potential, system
implicit none

  character(len=3) :: keyword !             
  integer      :: i
  real         :: coordinates(n,3)       ! n is a huge number
  real         :: energy, system_energy
  type(system) :: test_system

  call test_system%init ( keyword ) 
  ! keyword tells which of the extensions of 'potential' is allocated

  do i = 1, n
    energy = test_system%pair_potential%eval ( ... )
    system_energy = system_energy + energy
  end do

end program

Я думаю, что моя главная проблема, связанная с производительностью, заключается в том, что я не понимаю, что на самом деле делает компилятор во время компиляции и какие вещи выполняются во время выполнения.

Итак, мои вопросы:

  1. Как и когда компилятор проверяет, какой экземпляр eval использовать?
  2. Когда ключевое слово известно во время компиляции, выполняется ли проверка типа на каждой итерации цикла?
  3. Было бы лучше, например, использовать указатель процедуры в основной программе и связать его в начале с соответствующей процедурой 'eval'?

Заранее большое спасибо!


person g.b.    schedule 11.11.2014    source источник


Ответы (1)


  1. Он имеет виртуальную таблицу процедур, которые можно вызывать для связывания для всех расширенных типов и решает во время выполнения из этой таблицы.

  2. Установка ключевого слова может не помочь, это зависит от того, насколько умен компилятор. Я бы использовал type вместо class, если тип известен во время компиляции. Это, скорее всего, пропустит поиск vtable.

  3. Указатель процедуры также повлияет на поток инструкций, хотя вы можете сохранить некоторую часть поиска в виртуальной таблице. Это действительно зависит от внутренностей, и стоит попробовать и измерить производительность.

person Vladimir F    schedule 11.11.2014