我正在尝试将openmp应用于以下代码段的parallize,如下所示。但是,没有openmp衍生产品,并行代码的运行速度比串行代码慢。我在64位Linux平台上运行并使用gfortran进行编译。 您对如何正确地做到这一点的意见和建议表示赞赏!
call omp_set_num_threads(4)
do i = 2, natoms - 1
rti(1:3) = R_for(i,1:3)
fti(1:3) = ftmp(i,1:3)
!$OMP PARALLEL DO DEFAULT(SHARED)&
!$OMP& private(rtij,rsqij,rsqijinv,sr2,sr6,sr12,vij,wij,fij,ftij,ncut)&
!$OMP& REDUCTION(+:vtmp,wtmp,ftmp,fti) &
!$OMP& firstprivate(i,rti,R_for)
do j = i + 1, natoms
rtij = rti - R_for(j,1:3)
rtij = rtij - boxl*idnint( rtij*boxlinv )
rsqij = sum(rtij**2)
if(rsqij.lt.rcutsq) then
rsqijinv = 1d0/rsqij
sr2 = sigsq*rsqijinv
sr6 = sr2*sr2*sr2
sr12 = sr6*sr6
vij = sr12 - sr6
vtmp = vtmp + vij
wij = vij + sr12
wtmp = wtmp + wij
fij = wij*rsqijinv
ftij = fij*rtij
fti = fti + ftij
ftmp(j,1:3) = ftmp(j,1:3) - ftij(1:3)
ncut = ncut + 1
endif
enddo
!$OMP END PARALLEL DO
ftmp(i,1:3) = fti(1:3)
enddo
答案 0 :(得分:1)
正如Tony Hopkinson所提到的,线程创建引入了一些开销,因此您应该将并行区域移出外部循环并将共享变量的赋值放入工作共享或单个构造中。
然后,您可以使用具有线程数长度的数组来存储线程局部部分和,而不是仅在循环完成后执行减少vtmp和wtmp,例如似乎无处可用,并且可以即使在外环之后也会减少。由于if条件,从迭代到迭代,你的循环可能会严重失衡,并且使用一些动态调度可能是有益的。