Fortran 带索引条件的两个do循环的OpenMP并行化
我已经尝试过并行化包含这样一个双do循环的代码。当然效率不高,但现在这不是什么大问题。 输出tauv为NaN。这是第一个问题 第二个问题是,“英特尔编译器”给出了一个致命错误,线程数小于最大线程数(对于我的机器等于8) 我该如何处理这些问题Fortran 带索引条件的两个do循环的OpenMP并行化,fortran,openmp,nested-loops,Fortran,Openmp,Nested Loops,我已经尝试过并行化包含这样一个双do循环的代码。当然效率不高,但现在这不是什么大问题。 输出tauv为NaN。这是第一个问题 第二个问题是,“英特尔编译器”给出了一个致命错误,线程数小于最大线程数(对于我的机器等于8) 我该如何处理这些问题 !$omp parallel do private(i,j, ro11,ro21,ro12,ro22, &
!$omp parallel do private(i,j, ro11,ro21,ro12,ro22, &
u11,u21,u12,u22, &
v11,v21,v12,v22, &
es11,es21,es12,es22, &
p11,p21,p12,p22, &
te11,te21,te12,te22, &
emu11,emu21,emu12,emu22) &
shared(i1l, i2l, j1l, j2l, emumax, tauv, tauvij, ro, u, v, es)
do i=i1l+2,i2l-2,2
do j=j1l+2,j2l-2,2
if (i.le.niii.and.i.ge.0.and.j.ge.0.and.j.le.nj.or.&
i.le.ni.and.i.ge.niik.and.j.gt.njjv.and.j.le.nj.or.&
i.le.ni.and.i.ge.niik.and.j.ge.0.and.j.lt.njjn&
.or.i.gt.niii.and.i.lt.niik.and.j.gt.njj0+i-niii&
.or.i.gt.niii.and.i.lt.niik.and.j.lt.njj0-i+niii) then
ro11=ro(i-1,j-1)
ro21=ro(i+1,j-1)
ro12=ro(i-1,j+1)
ro22=ro(i+1,j+1)
u11=u(i-1,j-1)
u21=u(i+1,j-1)
u12=u(i-1,j+1)
u22=u(i+1,j+1)
v11=v(i-1,j-1)
v21=v(i+1,j-1)
v12=v(i-1,j+1)
v22=v(i+1,j+1)
es11=es(i-1,j-1)
es21=es(i+1,j-1)
es12=es(i-1,j+1)
es22=es(i+1,j+1)
p11=(es11-0.5*ro11*(u11*u11+v11*v11))*ga1
p21=(es21-0.5*ro21*(u21*u21+v21*v21))*ga1
p12=(es12-0.5*ro12*(u12*u12+v12*v12))*ga1
p22=(es22-0.5*ro22*(u22*u22+v22*v22))*ga1
te11=p11/ro11
te21=p21/ro21
te12=p12/ro12
te22=p22/ro22
emu11=te11**1.5*(1.0+s1)/(te11+s1)
emu21=te21**1.5*(1.0+s1)/(te21+s1)
emu12=te12**1.5*(1.0+s1)/(te12+s1)
emu22=te22**1.5*(1.0+s1)/(te22+s1)
emumax=emu11
if (emu21.gt.emumax) then
emumax=emu21
end if
if (emu12.gt.emumax) then
emumax=emu12
end if
if (emu22.gt.emumax) then
emumax=emu22
end if
tauvij=re*flkv*hx*hx/emumax
if (tauvij .le. tauv) then
tauv=tauvij
endif
endif
enddo
enddo
!$omp end parallel do
问题是它执行时没有错误,但OpenMP do循环的计算速度比顺序循环慢
从您的:
1.)您的代码在OpenMP区域中仅使用1个线程(?):
! Set number of threads
nthreads = 1
call omp_set_num_threads(nthreads)
print *, 'The number of threads are used is ', omp_get_max_threads ( )
我会避免调用omp\u set\u num\u threads()。相反,使用环境变量OMP_NUM_threads指定线程数。对于unix计算机:export OMP\u NUM\u THREADS=
2.)在“可复制”示例中,并行化循环(第312行)缺少私有/共享声明?根据您在上面写的内容,修复到:
!$omp parallel do default(private) shared(i1l, i2l, j1l, j2l, emumax, tauv, tauvij, ro, u, v, es)
根据以上所有内容,我使用GNU Fortran编译器从我的机器(4c/4t)得到的结果是:
...
Executed time in SEQ code is 60.2720146
...
Executed time in OMP code is 27.1342430
欢迎,所有Fortran问题都使用tag。您的代码示例应该包含所有变量的声明,并且是可编译和可测试的。请务必阅读。请给出这样一个完整的例子和完整的代码输出,包括所有的错误信息。@VladimirF,最简单的例子是。问题是它执行时没有错误,但OpenMP do循环的计算速度比顺序循环慢。最简单的例子应该在问题本身中,而不是在注释中的链接中。请理解这不是调试服务,因此请尝试做一些努力。减少代码可能会删除不必要的内容,但仍会保留问题。“您使用的是英特尔Fortran编译器集环境变量OMP_NUM_THREADS。”为什么使用英特尔Fortran?这是标准的OpenMP方式。我从不使用
omp\u set\u num\u线程
。我同意你的看法。在GNU FortranOMP_get_max_threads()
中,即使未设置OMP_NUM_threads,也会返回最大线程数。emumax上还有一个争用条件,应使用reductio和tauv来处理。(也考虑如果EMUMAX在更新后,但在TaviVJ计算之前发生了什么,这是合理的吗?)