简体   繁体   English

Fortran:分段错误

[英]Fortran: segmentation fault

I know I once made a similar topic, but that one was different.我知道我曾经做过一个类似的话题,但那是不同的。 This time, adding a print statement does not change whether or not I get a segfault.这一次,添加打印语句不会改变我是否得到段错误。

    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

I'm not sure about the lastprivate(fermi) statement, but it doesn't matter at this moment.我不确定 lastprivate(fermi) 语句,但此刻无关紧要。 shared gives the same behaviour. shared 给出了相同的行为。

So, I run this script with 'first, second, third, fourth' being increased.因此,我在增加“第一、第二、第三、第四”的情况下运行此脚本。 Typical output:典型输出:

[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

Well, how to proceed.嗯,如何进行。 I looked at gdb python;我看了gdb python; run fortran_test.py, and found:运行 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

If I change things in the inner loop - for instance, removing the j,i loops and putting them to a constant - then I just get the segfault at a different line.如果我在内部循环中更改内容 - 例如,删除 j,i 循环并将它们设置为常量 - 那么我只会在不同的行获得段错误。

I think this has something to do with memory, because it triggers as N increases.认为这与内存有关,因为它会随着 N 的增加而触发。 However, the things I've tried (export GOMP_STACKSIZE, OMP_STACKSIZE, ulimit) haven't fixed it, and I see no difference using them.但是,我尝试过的东西(导出 GOMP_STACKSIZE、OMP_STACKSIZE、ulimit)并没有修复它,我认为使用它们没有区别。 (For the time being, I removed them). (暂时,我删除了它们)。

Finally, the command to compile (it is in f2py):最后,编译命令(在f2py中):

 f2py --fcompiler=gfortran --f90flags="-fopenmp -g" -lgomp -m -c populate populate.f90

As you can see, I'm quite stuck.正如你所看到的,我被困住了。 I hope some of you know how to solve the problem.我希望你们中的一些人知道如何解决这个问题。

My aim is to have N=100 run quickly (hence the openMP fortran function), but this shouldn't matter for the fortran code, should it?我的目标是让 N=100 快速运行(因此是 openMP fortran 函数),但这对于 fortran 代码应该无关紧要,是吗?

If you're wondering, 4GB ram and my swap is 3.1G (Linux Swap / Solaris).如果你想知道,4GB 内存和我的交换是 3.1G (Linux Swap / Solaris)。

Thank you!谢谢!

default(firstprivate) lastprivate(fermi) means that each thread receives a private copy of angle , radius , and fermi , with each being of size first x second x third x fourth . default(firstprivate) lastprivate(fermi)意味着每个线程接收一个angleradiusfermi的私有副本,每个的大小为first x second x third x fourth default(firstprivate) lastprivate(fermi) In my experience, private arrays are always allocated on the stack, even when the option to automatically turn big arrays into heap arrays is given.根据我的经验,私有数组始终分配在堆栈上,即使提供了自动将大数组转换为堆数组的选项也是如此。 Your code most likely crashes because of insufficient stack space.由于堆栈空间不足,您的代码很可能会崩溃。

Instead of having everything private, you should really take a look at the data dependency and pick the correct data-sharing classes.与其将所有内容都私有化,您应该真正查看数据依赖项并选择正确的数据共享类。 angle , angle_array , surface , and radius are never written to, therefore they all should be shared . angleangle angle_arraysurfaceradius永远不会被写入,因此它们都应该被shared present_surface is being modified and should be private . present_surface正在被修改,应该是private fermi is written to, but never at the same location by more than one thread, therefore it should also be shared . fermi被写入,但永远不会被多个线程写入同一位置,因此它也应该被shared Also, note that lastprivate won't have the expected result as it makes available the value of the corresponding variable that it has in the thread that executes the logically last iteration of the m -loop.另外,请注意lastprivate不会有预期的结果,因为它使执行m循环的逻辑上最后一次迭代的线程中的相应变量的值可用。 first , second , third , and fourth are simply treated as constants and should be shared . firstsecondthirdfourth被简单地视为常量,应该shared The loop variables, of course, are private , but that is automated by the compiler.循环变量当然是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

A very possible reason is the stack limit.一个很可能的原因是堆栈限制。 First run ulimit -s to check the stack limit for the process.首先运行ulimit -s来检查进程的堆栈限制。 You can use ulimit -s unlimited to set it as ulimited.您可以使用ulimit -s unlimited将其设置为 ulimited。 Then if it still crashes, try to increase the stack for OPENMP by setting OMP_STACKSIZE environmental variable to a huge value, like 100MB .然后,如果它仍然崩溃,请尝试通过将OMP_STACKSIZE环境变量设置为一个巨大的值来增加 OPENMP 的堆栈,例如100MB

Intel has a discussion at https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors .英特尔在https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors上进行了讨论。 It has more information of stack and heap memory.它有更多的堆栈和堆内存信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM