Выравнивание данных внутри структуры в Intel Fortran - PullRequest
0 голосов
/ 05 ноября 2018

Я пытаюсь выровнять в памяти следующий тип данных:

type foo
   real, allocatable, dimension(:) :: bar1, bar2
   !dir$ attributes align:64 :: bar1
   !dir$ attributes align:64 :: bar2
end type foo

type(foo), allocatable, dimension(:) :: my_foo
allocate(my_foo(1))
allocate(my_foo(1)%bar1(100))
allocate(my_foo(1)%bar2(100))

! somewhere here I need to tell the compiler that data is aligned
!    for a simple array with name `bar` I would just do:
!dir$ assume_aligned bar1: 64
!dir$ assume_aligned bar2: 64
!    but what do I do for the data type I have, something like this?
!dir$ assume_aligned my_foo(1)%bar1: 64
!dir$ assume_aligned my_foo(1)%bar2: 64

do i = 1, 100
   my_foo(1)%bar1(i) = 10.
   my_foo(1)%bar2(i) = 10.
end do

Как видите, это массив структур типа foo с двумя большими массивами bar1 и bar2 в качестве переменных, которые мне нужно выровнять вблизи границ кэша в памяти.

Я вроде знаю, как это сделать для простых массивов ( link ), но я не знаю, как это сделать для такого рода сложной структуры данных. А что, если my_foo был не размером 1, а размером, скажем, 100? Я перебираю их?

1 Ответ

0 голосов
/ 07 ноября 2018

Хорошо, дело полузакрытое. Решение оказалось довольно простым. Вы просто используете указатели и делаете assume_aligned для них. Это должно позаботиться об этом.

type foo
   real, allocatable, dimension(:) :: bar1, bar2
   !dir$ attributes align:64 :: bar1
   !dir$ attributes align:64 :: bar2
end type foo

type(foo), target, allocatable, dimension(:) :: my_foo
real, pointer, contiguous :: pt_bar1(:)
real, pointer, contiguous :: pt_bar2(:)
allocate(my_foo(1))
allocate(my_foo(1)%bar1(100))
allocate(my_foo(1)%bar2(100))

pt_bar1 = my_foo(1)%bar1
pt_bar2 = my_foo(1)%bar2
!dir$ assume_aligned pt_bar1:64, pt_bar2:64

pt_bar1 = 10.
pt_bar2 = 10.

do петли все еще не векторизованы. Как если бы я сделал то же самое, как это

do i = 1, 100
   pt_bar1(i) = 10.
   pt_bar2(i) = 10.
end do

оно не будет векторизовано.

UPD. Хорошо, это делает работу (также необходимо добавить флаг -qopenmp-simd в компилятор):

!$omp simd
!dir$ vector aligned
do i = 1, 100
   pt_bar1(i) = 10.
   pt_bar2(i) = 10.
end do

Также, если вы просматриваете my_foo(j)%..., обязательно освобождайте указатели после каждой итерации с помощью pt_bar1 => null() и т. Д.

PS. Спасибо BW из нашего отдела за эту помощь. :) Иногда личное общение> stackoverflow (не всегда, только иногда).

...