在尝试优化某些代码时,我发现使用OpenMP线性增加了运行所需的时间。我试图加速的代码部分代码如下:
CALL system_clock(count_rate=cr)
CALL system_clock(count_max=cm)
rate = REAL(cr)
CALL SYSTEM_CLOCK(c1)
DO k=1,ntotal
CALL OMP_INIT_LOCK(locks(k))
END DO
!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i,j,k)
DO k=1,niac
i = pair_i(k)
j = pair_j(k)
dvx(:,k) = vx(:,i)-vx(:,j)
CALL omp_set_lock(locks(i))
CALL DGER(dim,dim,-1.d0, (disp_nmh(:,j)-disp_nmh(:,i)),1, &
(dwdx_nor(dim+1:2*dim,k)*V_0(j)),1, particle_data(i)%def_grad,dim)
CALL DGER(dim,dim,-1.d0, (-dvx(:,k)),1, &
(dwdx_nor(dim+1:2*dim,k)*V_0(j)) ,1, particle_data(i)%vel_grad(1:dim,1:dim),dim)
CALL omp_unset_lock(locks(i))
CALL omp_set_lock(locks(j))
CALL DGER(dim,dim,-1.d0, (dvx(:,k)),1, &
(dwdx_nor(3*dim+1:4*dim,k)*V_0(i)) ,1, particle_data(j)%vel_grad(1:dim,1:dim),dim)
CALL DGER(dim,dim,-1.d0, (disp_nmh(:,i)-disp_nmh(:,j)),1, &
(dwdx_nor(3*dim+1:4*dim,k)*V_0(i)),1, particle_data(j)%def_grad,dim)
CALL omp_unset_lock(locks(j))
END DO
!$OMP END PARALLEL DO
CALL SYSTEM_CLOCK(c2)
t_el = t_el + (c2-c1)/rate
WRITE(*,*) "Wall time elapsed: ", t_el
请注意,对于模拟,我正在测试k = 14000,我认为这是并行运行的合理候选者。据我所知,我必须使用锁来确保给出相同值“i”(但不同值为“j”)的线程无法访问正在写入的数组的相同索引。同时。我无法弄清楚我使用的BLAS(sudo apt-get install libblas-dev liblapack-dev
)的版本是否是线程安全的。我运行了8个核心的模拟,并得到了与没有OpenMP相同的结果,所以我猜它可能是。在这种情况下,BLAS用于计算和求和许多3×3矩阵的外积。
OpenMP的实现是否是加速此代码的最佳方式?我对OpenMP知之甚少,但我的猜测是:
明显超过了性能优势。它是否正确?或者可以修改上面的代码以获得一些性能提升?
修改
我应该补充一点,上面的代码是时间积分循环的一部分。希望这能解释为什么将经过的时间相加。