Использование кэша и производные типы
Я новичок в профилировании кода с помощью valgrind и cachegrind, и недавно я начал использовать эти инструменты, чтобы посмотреть, как мой код работает с использованием кэша. Я обнаружил, что простое выражение if, по-видимому, вызывает пропадание кэша почти каждый раз, когда он выполняется. В качестве примера я использую следующие производные типы в моей программе на Фортране:
type :: particle
real(pr), dimension(3) :: r = 0.0_pr ! position
real(pr), dimension(3) :: p = 0.0_pr ! momentum
end type particle
type :: rcell ! position cell
integer, dimension(6) :: bpoints = 0 ! cell grid points
integer :: np = 0 ! number of particles in cell
type(particle), dimension(50) :: parts ! particles in cell
end type rcell
type(rcell), dimension(:), allocatable :: rbin ! position space bins
allocate(rbin(100))
Этот пример представляет собой 100 ячеек в пространстве позиций, которые могут содержать до 50 частиц, описываемых их положением и импульсом. Код использует простой движитель частиц для обновления положения и импульса частиц на заданном временном шаге. Чтобы реализовать это, я использую цикл, подобный следующему:
do i = 1, numcells
if (rbin(i)%np == 0) cycle ! skip cells with no particles
...
end do
Включив оператор if, я решил, что я буду ускорять код, циклически повторяя цикл, когда в данной ячейке нет частиц. Однако я провел некоторое профилирование своего кода, используя valgrind с инструментом cachegrind, и обнаружил, что это простое выражение if почти всегда приводит к пропаданию кэша. Ниже приведен пример результатов этого оператора if с использованием cg_annotate с --auto=yes
опция включена:
Ir: 21,600,000
I1mr: 0
ILmr: 0
Dr: 4,320,000
D1mr: 4,319,057
DLmr: 4,318,979
Dw: 0
D1mw: 0
DLmw: 0
Это кажется пропуском кеша почти каждый раз, когда он выполняется. Я часто делаю это в своем коде, когда зацикливаюсь на ячейках, и я думаю, что это вызывает значительное замедление. Является ли это следствием использования производных типов? Есть ли способ улучшить использование кэша здесь, или с производными типами в целом?
Для полноты я компилирую с помощью gfortran 4.8.3 и использую следующие флаги: -g -O3 -ffast-math -mcmodel=medium -fdefault-real-8