Fortran Do проблема с индексом цикла для оптимизации кода

Прежде всего, мой английский не очень хорош. Мне жаль.

Насколько я знаю. Фортран адрес является главным столбцом. Мой старый код на Фортране давно не оптимизирован. Я пытаюсь изменить свой индекс кода Fortran90 для лучшей скорости.

Код - это почти 3-х мерная матрица. (I, J, K) и почти Do-цикл о я и J. размеры i и j составляют около 2000~3000, а k равно 2, это означает x,y

Порядок индекса моего старого кода (i, k, j)

например

Do j = 1 : 1500
    Do i = 1 : 1024
        AA(i, 1, j) = ... ;
        AA(i, 2, j) = ... ;
    end do
end do

В моем коде их много.

Поэтому я изменил порядок индекса. например (i, j, k), (k, i, j), (i, k, j), я думаю, (k, i, j) - лучший выбор в фортране (основной столбец).

но результата нет.

все 3 случая [ (i, j, k), (k, i, j), (i, k, j) ] тратятся почти на время. (1961, 1955, 1692).

Мой программный код такой длинный, и итерации достаточно для сравнения ( 32000)

Ниже мой вариант компиляции.

ifort -O3 -xHost -ipo -qopenmp -fp-model strict -mcmodel=medium

Я не понимаю приведенный выше результат. Пожалуйста, помогите мне.

Спасибо, что прочитали.

Кроме того, ниже одна из моих программ. матрица L_X(i,:, j) - моя цель: 1 и 2

!$OMP Parallel DO private(j,i,ii,Tan,NormT)

do j=1,LinkPlusBndry
  if (Kmax(j)>2) then
     i=1; Tan=L_X(i+1,:,j)-L_X(i,:,j); NormT=sqrt(Tan(1)**2+Tan(2)**2)
     if (NormT < min_dist) then
        L_X(2:Kmax(j)-1,:,j)=L_X(3:Kmax(j),:,j)
        Kmax(j)=Kmax(j)-1
     elseif (NormT > max_dist) then
        do i=Kmax(j)+1,3,-1; L_X(i,:,j)=L_X(i-1,:,j); end do
        L_X(2,:,j)=(L_X(1,:,j)+L_X(3,:,j))/2.0_dp
        Kmax(j)=Kmax(j)+1
     end if
     do i=2,M-1
       if (i > (Kmax(j)-2) ) exit
       Tan=L_X(i+1,:,j)-L_X(i,:,j); NormT=sqrt(Tan(1)**2+Tan(2)**2)
       if (NormT < min_dist) then
         L_X(i,:,j)=(L_X(i,:,j)+L_X(i+1,:,j))/2.0_dp
         L_X(i+1:Kmax(j)-1,:,j)=L_X(i+2:Kmax(j),:,j)
         Kmax(j)=Kmax(j)-1
       elseif (NormT > max_dist) then
         do ii=Kmax(j)+1,i+2,-1; L_X(ii,:,j)= L_X(ii-1,:,j); end do
         L_X(i+1,:,j)=(L_X(i,:,j)+L_X(i+2,:,j))/2.0_dp
         Kmax(j)=Kmax(j)+1
       end if
     end do
     i=Kmax(j)-1;
     if (i>1) then
       Tan=L_X(i+1,:,j)-L_X(i,:,j); NormT=sqrt(Tan(1)**2+Tan(2)**2)
       if (NormT < min_dist) then
         L_X(Kmax(j)-1,:,j)=L_X(Kmax(j),:,j)
         Kmax(j)=Kmax(j)-1
       elseif (NormT > max_dist) then
         L_X(Kmax(j)+1,:,j)= L_X(Kmax(j),:,j)
         L_X(Kmax(j),:,j)=(L_X(Kmax(j)-1,:,j)+L_X(Kmax(j)+1,:,j))/2.0_dp
          Kmax(j)=Kmax(j)+1
       end if
     end if
  elseif (Kmax(j)==2) then
     i=1; Tan=L_X(i+1,:,j)-L_X(i,:,j); NormT=sqrt(Tan(1)**2+Tan(2)**2)
     if (NormT > max_dist) then
        do i=Kmax(j)+1,3,-1; L_X(i,:,j)=L_X(i-1,:,j); end do
        L_X(2,:,j)=(L_X(1,:,j)+L_X(3,:,j))/2.0_dp
        Kmax(j)=Kmax(j)+1
     end if
  end if
  do i=Kmax(j)+1,M; L_X(i,:,j)=L_X(Kmax(j),:,j); end do
end do

!$OMP End Parallel DO

1 ответ

Решение

Я бы не стал так сильно беспокоиться о порядке следования петель. Оптимизация ifort -O3 - это агрессивный оптимизатор цикла. Вполне возможно, что изменение порядка трехмерных массивов практически не повлияет.

Насколько вы думаете (k,i,j) - лучший порядок. В общем, это было бы лучше всего. Но у k только 2 элемента, а у меня 1024. Предполагается, что вы используете вещественную одинарную точность (4 байта). Этот 2-D сегмент вашего 3-D массива умещается в 8K RAM. Вполне вероятно, что ваши данные после запуска цикла полностью находятся в кэше ЦП, поэтому упорядочение индекса не будет иметь значения. Вам нужны гораздо большие измерения данных, чтобы эффект, который вы рассматриваете, вступил в силу.

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

Другие вопросы по тегам