我有一个fortran代码,其中我有一个并行部分。它由gfortran
成功编译,但是通过运行它会出现分段错误。串行编译的运行文件不显示任何错误。我还用非常小的输入矩阵(rho1& rho2)检查了并行程序,并测试了逐步参数。没有错。如果我理解正确,当我将变量确定为PRIVATE
时,则无需使用
$OMP ATOMIC
。这里矩阵rho1和rho2的尺寸约为15,000,000。这是代码的并行部分:
!$OMP PARALLEL DO ORDERED DEFAULT(PRIVATE)
do ix = 1 , nx
do iy = 1 , ny
do iz = 1 , nz
k = iz + (iy-1) * nz + (ix-1) * ny * nz
if (rho1(k) .GT. 0.d0) then
x1 = x0 + ((ix-1) * dx)
y1 = y0 + ((iy-1) * dy)
z1 = z0 + ((iz-1) * dz)
rr = (x1-xa)**2 + (y1-ya)**2 + (z1-za)**2
r1a = dsqrt (rr)
rr = (x1-xb)**2 + (y1-yb)**2 + (z1-zb)**2
r1b = dsqrt (rr)
if (r1a == 0.d0) Vnuc = (rho1(k) * Znb)/r1b
if (r1b == 0.d0) Vnuc = (rho1(K) * Zna)/r1a
if (r1a .GT. 0.d0 .AND. r1b .GT. 0.d0) then
Vnuc = (rho1(k) * Zna)/r1a + (rho1(K) * Znb)/r1b
endif
Ve = 0
!$OMP ORDERED
j = 1
do jx = 1 , nx
do jy = 1 , ny
do jz = 1 , nz
if (rho2(j) .GT. 0.d0) then
x2 = x0 + ((jx-1) * dx)
y2 = y0 + ((jy-1) * dy)
z2 = z0 + ((jz-1) * dz)
rr= (x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2
r12 = dsqrt (rr)
if (r12 .GT. 0.d0) then
Ve = Ve + (rho1(k)*rho2(j))/r12
endif
endif
j = j + 1
enddo
enddo
enddo
!$OMP END ORDERED
V1 = (Ve * dx * dy * dz * 0.529177d0) - Vnuc
rr = (x1-xmid)**2 + (y1-ymid)**2 + (z1-zmid)**2
r = dsqrt (rr)
zef1(k) = V1 * r
endif
enddo
enddo
enddo
!$OMP END PARALLEL DO
答案 0 :(得分:2)
看起来您的数组rho1
和rho2
被声明为私有。这样做的一个结果是每个线程在进入并行区域时将具有这些阵列的私有实例。如果数组很大,程序可能只是尝试分配比可用内存更多的内存。
在没有共享的大型阵列上编写OpenMP程序是相对不寻常的;在大型共享阵列的不同部分上运行的多个线程可能是OpenMP的规范应用程序。
答案 1 :(得分:1)
我从网站上的其他帖子中找到了解决方案,“为什么在这个openmp代码中发生了分段错误”。 问题是由于堆栈大小的限制。 它通过以下命令解决: ulimit -s unlimited
答案 2 :(得分:1)
一个问题也可能是当变量被声明为私有时,每个线程都会创建一个对象的单元化私有副本。您可能需要包含copyin openmp语句,以便私有变量在并行化区域之前具有变量的值。