Caching 缓存阻塞和预取

Caching 缓存阻塞和预取,caching,fortran,prefetch,tiling,Caching,Fortran,Prefetch,Tiling,我试图测试一个手动缓存阻塞或循环平铺优化的有效性,该优化已应用于一些Fortran科学代码例程。关于瓷砖大小的选择,我使用了一种基于经典不同线估计的算法。我正在使用英特尔Fortran编译器ifort 18.0.1(2018) 代码是用xHost编译标志编译的。为了观察基本版本和平铺版本之间的任何加速,我必须将预取级别切换到2(使用-qopt prefetch=2)。通过这样做,我实际上获得了27%的加速(24秒对33秒)。对于普通O3 xHost,执行时间保持不变(20秒)——因此基本和平铺之

我试图测试一个手动缓存阻塞或循环平铺优化的有效性,该优化已应用于一些Fortran科学代码例程。关于瓷砖大小的选择,我使用了一种基于经典不同线估计的算法。我正在使用英特尔Fortran编译器ifort 18.0.1(2018)

代码是用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 normal运行时观察到任何加速?问题应该是O3引入的攻击性SW预取(这应该是-qopt 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
但这似乎对我没有帮助。任何一种建议都将不胜感激


致以最诚挚的问候。

您正在谈论的对象的尺寸是什么(
pwn
ptb
zwz
,…)。最重要的是:
zfp_wk
是或
0
2*pwn(ji,jj,jk)
zfm_wk
的dito。这可能意味着
zwz
可以使用
WHERE
计算。我不认为
WHERE
可以使任何事情更快,我预期的恰恰相反。即使没有用,也最好计算更多,并避免分支。这些对象的维度是
jpi X jpj X jpk
。基于循环边界,这些维度和下标I通过使用不同的线估计来计算平铺大小。但是,对于正常的O3 xHost,改变瓷砖大小不会产生任何影响。似乎激进的预取会干扰缓存阻塞,但我很想知道是否可以通过缓存阻塞进行更多改进