我是编码Fortran的初学者,仍然在主要的学习过程中。 我在Fortran中为FE Simulation编写了一个程序。但表现仍然太慢。 因此,我首先实现了稀疏矩阵,这很好地加快了代码的速度。但它仍然不够快。 这就是为什么我认为使用openMP和并行化部分代码会非常有用。 但是当我尝试实现openMP的命令时,要么代码运行得比以前慢(我假设开销太大),要么它不再正确执行。
在即将到来的部分代码之前,有一个do循环用于时间步进。 变量nE非常高,可以说高达50K或更高。必须为每个时间步计算该循环。 它是我想要并行化的代码的一部分:
!$omp parallel
!$omp do private(v, b, N_loc, c, n, vertices, a1, a2, a3, b1, b2, b3, etc...)
do v = 1, nE
do b = 1, 4
N_loc(1,b) = umesh_elt(v,b) !Extracting node numbers
c(1,b) = c_s(N_loc(1,b),1) !Extracting values
n(1,b) = n_s(N_loc(1,b),1)
vertices(b,1) = umesh_co(N_loc(1,b),1) !Extracting coordinates
vertices(b,2) = umesh_co(N_loc(1,b),2) !Extracting coordinates
end do
a1 = 0.25*(-vertices(1,1)+vertices(2,1)+vertices(3,1)-vertices(4,1))
a2 = 0.25*(-vertices(1,1)-vertices(2,1)+vertices(3,1)+vertices(4,1))
a3 = 0.25*(+vertices(1,1)-vertices(2,1)+vertices(3,1)-vertices(4,1))
b1 = 0.25*(-vertices(1,2)+vertices(2,2)+vertices(3,2)-vertices(4,2))
b2 = 0.25*(-vertices(1,2)-vertices(2,2)+vertices(3,2)+vertices(4,2))
b3 = 0.25*(+vertices(1,2)-vertices(2,2)+vertices(3,2)-vertices(4,2))
do j = 1, nGauss
J_c(1,1) = a1 + a3*QuadRuleX(j,2)
J_c(1,2) = a2 + a3*QuadRuleX(j,1)
J_c(2,1) = b1 + b3*QuadRuleX(j,2)
J_c(2,2) = b2 + b3*QuadRuleX(j,1)
J_det(j,1) = J_c(1,1)*J_c(2,2) - J_c(1,2)*J_c(2,1)
end do
do k = 1, 4
y(k,1) = 0.0
do z = 1, nGauss
r = QuadRuleX(z,1)
t = QuadRuleX(z,2)
if (k == 1) then
phi = 0.25*(r-1)*(t-1)
else if (k == 2) then
phi = -0.25*(r+1)*(t-1)
else if (k == 3) then
phi = 0.25*(r+1)*(t+1)
else if (k == 4) then
phi = -0.25*(r-1)*(t+1)
endif
phi_1 = 0.25*(r-1)*(t-1)
phi_2 = -0.25*(r+1)*(t-1)
phi_3 = 0.25*(r+1)*(t+1)
phi_4 = -0.25*(r-1)*(t+1)
c_h = c(1,1)*phi_1+c(1,2)*phi_2+c(1,3)*phi_3+c(1,4)*phi_4
n_h = n(1,1)*phi_1+n(1,2)*phi_2+n(1,3)*phi_3+n(1,4)*phi_4
y(k,1)=(phi*((((hi-1)*c_h+hi)/(2*(hi-1)*c_h+1))*n_h* (2-n_h)-n_h))*J_det(z,1)*QuadRuleW(z,1)+y(k,1)
end do
end do
S(z1,1) = y(1,1)+S(z1,1)
S(z2,1) = y(2,1)+S(z2,1)
S(z3,1) = y(3,1)+S(z3,1)
S(z4,1) = y(4,1)+S(z4,1)
end do
!$omp end do
!omp end parallel
在这段代码之后,有一个时间步骤结束循环和一些if子句来停止模拟,如果发生了特定的事情。
我用选项编译它 ifort -mkl -openmp NAME.f90 当试图用它来执行时 时间./a.out 代码无法正常运行,程序启动和停止没有任何错误。
我认为我基本上做错了,就像我没有正确理解如何正确设置那些使用openMP做的循环。有人有什么建议吗?
感谢任何帮助,非常感谢! ·阿尔
答案 0 :(得分:0)
这对评论来说有点太长了,所以我会将其作为答案发布......
如果没有整个PRIVATE()
陈述,很难说出什么是全局的,什么是本地的......
乍一看,只有S(,1) = y(,1)+S(,1)
行似乎很重要。你能确保没有两个线程同时尝试访问同一个S(,1)
吗?从我看到的z1
- z4
设置在之外的循环 - 所以我的猜测是它们对于所有线程都是相同的并且发生了race condition。
如果它们是相同的,这就像reduction
操作一样。作为一个快速修复(仅用于调试,除非你真的需要它,否则不要使用它)你可以将该代码阻塞到critical
部分。