Я пытаюсь проверить эффективность ручной блокировки кэша или оптимизации циклического разбиения, которая была применена к некоторой рутине научного кода на Фортране. Что касается выбора размера тайлов, я использовал алгоритм, основанный на классической оценке различных линий. Я использую Intel Fortran Compiler ifort 18.0.1 (2018)
Код скомпилирован с флагами компиляции O3 xHost. Чтобы наблюдать какое-либо ускорение между базовой версией и мозаичной версией, я должен переключить уровень предварительной выборки на 2 (с помощью -qopt-prefetch = 2). Делая это, я фактически получаю 27% ускорения (24 секунды против 33 секунд). При обычном O3 xHost время выполнения остается неизменным (20 секунд), поэтому я не вижу разницы между основанием и плиткой.
Гнездо простого цикла следующее, базовая версия:
DO jk = 2, jpkm1 ! Interior value ( multiplied by wmask)
DO jj = 1, jpj
DO ji = 1, jpi
zfp_wk = pwn(ji,jj,jk) + ABS( pwn(ji,jj,jk) )
zfm_wk = pwn(ji,jj,jk) - ABS( pwn(ji,jj,jk) )
zwz(ji,jj,jk) = 0.5 * ( zfp_wk * ptb(ji,jj,jk,jn) + zfm_wk * ptb(ji,jj,jk-1,jn) ) * wmask(ji,jj,jk)
END DO
END DO
END DO
и оптимизированная версия:
DO jltj = 1, jpj, OBS_UPSTRFLX_TILEY
DO jk = 2, jpkm1
DO jj = jltj, MIN(jpj, jltj+OBS_UPSTRFLX_TILEY-1)
DO ji = 1, jpi
zfp_wk = pwn(ji,jj,jk) + ABS( pwn(ji,jj,jk) )
zfm_wk = pwn(ji,jj,jk) - ABS( pwn(ji,jj,jk) )
zwz(ji,jj,jk) = 0.5 * ( zfp_wk * ptb(ji,jj,jk,jn) + zfm_wk * ptb(ji,jj,jk-1,jn) ) * wmask(ji,jj,jk)
END DO
END DO
END DO
END DO
Почему я не могу наблюдать ускорение при нормальной работе O3 xHost? Проблема должна заключаться в агрессивной предварительной загрузке ПО, введенной O3 (что должно быть следствием флага оптимизации -3opt-prefetch = 3 O3), но я бы знал, смогу ли я продолжить оптимизацию с блокировкой кэша. Я пробовал какую-то ручную предварительную загрузку ПО, например:
DO jltj = 1, jpj, OBS_UPSTRFLX_TILEY
DO jk = 2, jpkm1
DO jj = jltj, MIN(jpj, jltj+OBS_UPSTRFLX_TILEY-1)
DO ji = 1, jpi
zfp_wk = pwn(ji,jj,jk) + ABS( pwn(ji,jj,jk) )
zfm_wk = pwn(ji,jj,jk) - ABS( pwn(ji,jj,jk) )
zwz(ji,jj,jk) = 0.5 * ( zfp_wk * ptb(ji,jj,jk,jn) + zfm_wk * ptb(ji,jj,jk-1,jn) ) * wmask(ji,jj,jk)
IF(jk== jpkm1 .AND. jj == MIN(jpj, jltj+OBS_UPSTRFLX_TILEY-1)-2) THEN
CALL mm_prefetch(pwn(1,jltj+OBS_UPSTRFLX_TILEY,1), 1)
CALL mm_prefetch(zwz(1,jltj+OBS_UPSTRFLX_TILEY,1), 1)
CALL mm_prefetch(ptb(1,jltj+OBS_UPSTRFLX_TILEY,1,jn), 1)
CALL mm_prefetch(wmask(1,jltj+OBS_UPSTRFLX_TILEY,1), 1)
ENDIF
END DO
END DO
END DO
END DO
но это, похоже, не помогает мне. Любые предложения будут очень благодарны.
С уважением.