放置 omp pragma 的明显位置是最外面的循环。
对于每个 (l,m,n),您都在计算扰动变量和指数平滑器之间的卷积。每个 (l,m,n) 计算都完全独立于其他计算,因此您可以将其放在最外层循环上。例如最简单的事情
!$omp parallel do private(n,m,l,i,j,k,exp_smoother) shared(sum_u_pert,sum_v_pert,sum_t_pert,u_p,v_p,t_p), default(none)
do n=1,lm
do m=1,jm
do l=1,im
do k=1,lm
do j=1,jm
do i=1,im
exp_smoother=exp(-(abs(i-l)/hzscl)-(abs(j-m)/hzscl)-(abs(k-n)/vscl))
sum_u_pert(l,m,n) = sum_u_pert(l,m,n) + u_p(i,j,k) * exp_smoother
sum_v_pert(l,m,n) = sum_v_pert(l,m,n) + v_p(i,j,k) * exp_smoother
sum_t_pert(l,m,n) = sum_t_pert(l,m,n) + t_p(i,j,k) * exp_smoother
end do
end do
end do
end do
end do
end do
在 8 核上给我带来约 6 倍的加速(使用大大减少的问题大小 20x41x41)。考虑到循环中要做的工作量,即使是较小的大小,我认为它不是 8 倍加速的原因涉及内存争用或错误共享;为了进一步调整性能,您可能需要显式地将总和数组分解为每个线程的子块,并在最后将它们组合起来;但根据问题的大小,拥有相当于额外的 im x jm x lm 大小的数组可能并不理想。
看起来这个问题有很多结构,你可以利用它来加快串行案例的速度,但说起来更容易找到它;在纸和笔上摆弄,几分钟之内什么也想不出来,但聪明的人可能会发现一些东西。