Fortran:分段错误
Fortran: segmentation fault
我知道我曾经做过类似的话题,但那个是不同的。这次,添加打印语句不会改变我是否遇到段错误。
call omp_set_num_threads(omp_get_max_threads())
!$omp parallel do &
!$omp default(firstprivate) &
!$omp private(present_surface) &
!$omp lastprivate(fermi)
do m = 1, fourth
do n = 1, third
do j = 1, second
do i = 1, first
!current angle is phi[i,j,ii,jj]
!we have to find the current fermi surface
present_surface = 0.
do a = 1, fourth
if (angle(i,j,n,m) == angle_array(a)) then
present_surface = surface(a)
end if
end do
if (radius(i,j,n,m) >= present_surface) then
fermi(i,j,n,m) = 0.
else
fermi(i,j,n,m) = 1.
end if
end do
end do
end do
end do
!$omp end parallel do
我不确定 lastprivate(fermi) 声明,但目前这并不重要。 shared 给出相同的行为。
所以,我运行这个脚本随着'first, second, third, fourth'的增加。典型输出:
[10] Time elapsed is 0.001 [s].
[15] Time elapsed is 0.002 [s].
[20] Time elapsed is 0.005 [s].
./compile: line 2: 4310 Segmentation fault python fortran_test.py
嗯,如何进行。我看了gdb python; 运行 fortran_test.py,发现:
(gdb) run fortran_test.py
Starting program: /usr/bin/python fortran_test.py
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffed9b0700 (LWP 4251)]
[New Thread 0x7fffe8ba5700 (LWP 4252)]
[New Thread 0x7fffe83a4700 (LWP 4253)]
[New Thread 0x7fffe7ba3700 (LWP 4254)]
[10] Time elapsed is 0.008 [s].
[15] Time elapsed is 0.004 [s].
[20] Time elapsed is 0.005 [s].
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe7ba3700 (LWP 4254)]
0x00007fffe8dc0bb7 in __populate_MOD_fermi_integrand._omp_fn.0 () at populate.f90:31
31 do n = 1, third
如果我更改内部循环中的内容 - 例如,删除 j,i 循环并将它们设置为常量 - 那么我只会在另一行出现段错误。
我认为这跟内存有关系,因为它随着N的增加而触发。但是,我尝试过的方法(export GOMP_STACKSIZE、OMP_STACKSIZE、ulimit)都没有修复它,我看不出使用它们有什么区别。 (暂时,我删除了它们)。
最后,编译命令(在f2py中):
f2py --fcompiler=gfortran --f90flags="-fopenmp -g" -lgomp -m -c populate populate.f90
如您所见,我被困住了。我希望你们中的一些人知道如何解决这个问题。
我的目标是快速获得 N=100 运行(因此有 openMP fortran 函数),但这对 Fortran 代码应该无关紧要,不是吗?
如果您想知道,4GB 内存和我的交换空间是 3.1G(Linux 交换空间/Solaris)。
谢谢!
default(firstprivate) lastprivate(fermi)
表示每个线程接收 angle
、radius
和 fermi
的私有副本,每个副本的大小为 first x second x third x fourth
。根据我的经验,私有数组总是分配在堆栈上,即使提供了自动将大数组转换为堆数组的选项也是如此。您的代码很可能因为堆栈不足 space.
而崩溃
与其将所有内容都设为私有,不如真正查看数据依赖性并选择正确的数据共享 类。 angle
、angle_array
、surface
和 radius
永远不会写入,因此它们都应该是 shared
。 present_surface
正在修改中,应该是 private
。 fermi
被写入,但绝不会被多个线程写入同一位置,因此它也应该是 shared
。另外,请注意 lastprivate
不会有预期的结果,因为它使它在执行 m
循环的逻辑上最后一次迭代的线程中具有的相应变量的值可用。 first
、second
、third
和 fourth
被简单地视为常量,应该是 shared
。循环变量当然是 private
,但这是由编译器自动生成的。
!$omp parallel do private(present_surface)
do m = 1, fourth
do n = 1, third
do j = 1, second
do i = 1, first
!current angle is phi[i,j,ii,jj]
!we have to find the current fermi surface
present_surface = 0.
do a = 1, fourth
if (angle(i,j,n,m) == angle_array(a)) then
present_surface = surface(a)
end if
end do
if (radius(i,j,n,m) >= present_surface) then
fermi(i,j,n,m) = 0.
else
fermi(i,j,n,m) = 1.
end if
end do
end do
end do
end do
!$omp end parallel do
一个很可能的原因是堆栈限制。首先 运行 ulimit -s
检查进程的堆栈限制。您可以使用 ulimit -s unlimited
将其设置为 ulimited。然后,如果它仍然崩溃,请尝试通过将 OMP_STACKSIZE
环境变量设置为一个巨大的值来增加 OPENMP 的堆栈,例如 100MB
.
英特尔在 https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors 进行了讨论。它有更多关于堆栈和堆内存的信息。
我知道我曾经做过类似的话题,但那个是不同的。这次,添加打印语句不会改变我是否遇到段错误。
call omp_set_num_threads(omp_get_max_threads())
!$omp parallel do &
!$omp default(firstprivate) &
!$omp private(present_surface) &
!$omp lastprivate(fermi)
do m = 1, fourth
do n = 1, third
do j = 1, second
do i = 1, first
!current angle is phi[i,j,ii,jj]
!we have to find the current fermi surface
present_surface = 0.
do a = 1, fourth
if (angle(i,j,n,m) == angle_array(a)) then
present_surface = surface(a)
end if
end do
if (radius(i,j,n,m) >= present_surface) then
fermi(i,j,n,m) = 0.
else
fermi(i,j,n,m) = 1.
end if
end do
end do
end do
end do
!$omp end parallel do
我不确定 lastprivate(fermi) 声明,但目前这并不重要。 shared 给出相同的行为。
所以,我运行这个脚本随着'first, second, third, fourth'的增加。典型输出:
[10] Time elapsed is 0.001 [s].
[15] Time elapsed is 0.002 [s].
[20] Time elapsed is 0.005 [s].
./compile: line 2: 4310 Segmentation fault python fortran_test.py
嗯,如何进行。我看了gdb python; 运行 fortran_test.py,发现:
(gdb) run fortran_test.py
Starting program: /usr/bin/python fortran_test.py
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffed9b0700 (LWP 4251)]
[New Thread 0x7fffe8ba5700 (LWP 4252)]
[New Thread 0x7fffe83a4700 (LWP 4253)]
[New Thread 0x7fffe7ba3700 (LWP 4254)]
[10] Time elapsed is 0.008 [s].
[15] Time elapsed is 0.004 [s].
[20] Time elapsed is 0.005 [s].
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe7ba3700 (LWP 4254)]
0x00007fffe8dc0bb7 in __populate_MOD_fermi_integrand._omp_fn.0 () at populate.f90:31
31 do n = 1, third
如果我更改内部循环中的内容 - 例如,删除 j,i 循环并将它们设置为常量 - 那么我只会在另一行出现段错误。
我认为这跟内存有关系,因为它随着N的增加而触发。但是,我尝试过的方法(export GOMP_STACKSIZE、OMP_STACKSIZE、ulimit)都没有修复它,我看不出使用它们有什么区别。 (暂时,我删除了它们)。
最后,编译命令(在f2py中):
f2py --fcompiler=gfortran --f90flags="-fopenmp -g" -lgomp -m -c populate populate.f90
如您所见,我被困住了。我希望你们中的一些人知道如何解决这个问题。
我的目标是快速获得 N=100 运行(因此有 openMP fortran 函数),但这对 Fortran 代码应该无关紧要,不是吗?
如果您想知道,4GB 内存和我的交换空间是 3.1G(Linux 交换空间/Solaris)。
谢谢!
default(firstprivate) lastprivate(fermi)
表示每个线程接收 angle
、radius
和 fermi
的私有副本,每个副本的大小为 first x second x third x fourth
。根据我的经验,私有数组总是分配在堆栈上,即使提供了自动将大数组转换为堆数组的选项也是如此。您的代码很可能因为堆栈不足 space.
与其将所有内容都设为私有,不如真正查看数据依赖性并选择正确的数据共享 类。 angle
、angle_array
、surface
和 radius
永远不会写入,因此它们都应该是 shared
。 present_surface
正在修改中,应该是 private
。 fermi
被写入,但绝不会被多个线程写入同一位置,因此它也应该是 shared
。另外,请注意 lastprivate
不会有预期的结果,因为它使它在执行 m
循环的逻辑上最后一次迭代的线程中具有的相应变量的值可用。 first
、second
、third
和 fourth
被简单地视为常量,应该是 shared
。循环变量当然是 private
,但这是由编译器自动生成的。
!$omp parallel do private(present_surface)
do m = 1, fourth
do n = 1, third
do j = 1, second
do i = 1, first
!current angle is phi[i,j,ii,jj]
!we have to find the current fermi surface
present_surface = 0.
do a = 1, fourth
if (angle(i,j,n,m) == angle_array(a)) then
present_surface = surface(a)
end if
end do
if (radius(i,j,n,m) >= present_surface) then
fermi(i,j,n,m) = 0.
else
fermi(i,j,n,m) = 1.
end if
end do
end do
end do
end do
!$omp end parallel do
一个很可能的原因是堆栈限制。首先 运行 ulimit -s
检查进程的堆栈限制。您可以使用 ulimit -s unlimited
将其设置为 ulimited。然后,如果它仍然崩溃,请尝试通过将 OMP_STACKSIZE
环境变量设置为一个巨大的值来增加 OPENMP 的堆栈,例如 100MB
.
英特尔在 https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors 进行了讨论。它有更多关于堆栈和堆内存的信息。