Caching 缓存阻塞和预取
我试图测试一个手动缓存阻塞或循环平铺优化的有效性,该优化已应用于一些Fortran科学代码例程。关于瓷砖大小的选择,我使用了一种基于经典不同线估计的算法。我正在使用英特尔Fortran编译器ifort 18.0.1(2018) 代码是用xHost编译标志编译的。为了观察基本版本和平铺版本之间的任何加速,我必须将预取级别切换到2(使用-qopt prefetch=2)。通过这样做,我实际上获得了27%的加速(24秒对33秒)。对于普通O3 xHost,执行时间保持不变(20秒)——因此基本和平铺之间没有区别 简单的循环嵌套如下所示,即基本版本: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秒)——因此基本和平铺之
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,改变瓷砖大小不会产生任何影响。似乎激进的预取会干扰缓存阻塞,但我很想知道是否可以通过缓存阻塞进行更多改进