Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 启用$OMP DO循环时出现分段错误_Fortran_Openmp - Fatal编程技术网

Fortran 启用$OMP DO循环时出现分段错误

Fortran 启用$OMP DO循环时出现分段错误,fortran,openmp,Fortran,Openmp,我正在尝试修改旧代码以使用openmp初始化阵列。但是,在下面的代码部分中启用$OMP DO派生时,我遇到了分段错误。请你指出可能出了什么问题好吗 我使用fortran,并使用gfortran编译,变量被声明为公共变量 common/quant/keosc,vosc,rosc,frt,grt,dipole,v_solv common/quant_avg/frt_avg,grt_avg,d_coup,rv_avg,b_avg !$OMP PARALLEL !$OMP DO

我正在尝试修改旧代码以使用openmp初始化阵列。但是,在下面的代码部分中启用$OMP DO派生时,我遇到了分段错误。请你指出可能出了什么问题好吗

我使用fortran,并使用gfortran编译,变量被声明为公共变量

   common/quant/keosc,vosc,rosc,frt,grt,dipole,v_solv
   common/quant_avg/frt_avg,grt_avg,d_coup,rv_avg,b_avg

    !$OMP PARALLEL 
!$OMP DO private(m,j,l,mp) firstprivate(nstates,natoms) lastprivate(rv_avg,b_avg,grt_avg,frt_avg,d_coup)
      do m = 0, nstates - 1 
         rv_avg(m) = 0d0
         b_avg(m) = 0d0
         do j = 1, 3
            grt_avg(m,j) = 0d0
            do l = 1, natoms
               frt_avg(m,l,j) = 0d0           
               do mp = 0, nstates - 1         
                  d_coup(m,mp,l,j) = 0d0         
               enddo                          
            enddo
         enddo
      enddo
!$OMP END DO
!$OMP END PARALLEL

您是否测量了程序中CPU消耗的位置?加速那些不消耗太多CPU时间的部分是一种浪费。如果数组初始化占CPU使用量的比例很高,我会感到惊讶。如果改用数组表示法,代码的可读性会更高,例如,
rv_avg(0:nstates-1)=0d0

您没有显示任何数组的维度声明,因此我推测

do m = 0, nstates - 1 
     rv_avg(m) = 0d0
写入不存在的
rv_avg
元素,即索引
0
处的元素。由于Fortran程序在默认情况下不会检查数组元素访问是否在边界内,因此运行时不会捕获边界外的写入。如果执行时写操作停留在程序的地址空间内,则不会导致分段错误。给定公共块声明,
rv_avg
0
-th元素很可能是
d_coup
的一部分

通过引入OpenMP,改变变量到地址空间的映射,很容易相信
rv_avg
0
-th元素现在位于线程的地址空间之外,并导致分段错误

由于程序对
0
处的数组元素进行了其他引用,因此其中任何一个都可能是分段错误的根源


当然,如果您遵循@M.S.B.的建议并使用数组语法符号,则可以避免越界数组访问。

问题可能是OpenMP线程中没有足够的堆栈空间来保存所有这些数组的私有副本。特别是
d_coup
看起来像是一个非常大的,有
3个natoms x nstates^2个
元素。如今,大多数Fortran编译器会自动对如此大的数组使用堆分配,但当涉及到
(first | last)private
变量时,一些OpenMP编译器,包括GCC和Intel Fortran编译器,总是将它们放在堆栈上。更多信息请参见我的答案


编辑:现在我看到M.S.B.在他的评论中实际上已经链接到了同一个问题。

感谢您的关注和评论。我知道这不会有太大的性能提升。但我想知道为什么会出现错误,尤其是我在openmp中对常见变量所做的任何错误。另外,对于来自的信息,与原始数组表示法相比,f90数组表示法的性能有所下降。我怀疑使用数组表示法进行初始化会导致性能下降。编译器越来越好了。测量并找出。。。关于分段错误:可能是堆栈大小问题。请参见使用数组表示法时,例如,
rv_avg(:)=0d0
gfortran
如果赋值语句放置在OpenMP
并行工作共享
构造中,则生成并行代码。但是,它不适用于向量赋值,例如,在工作共享结构中,仍然会导致串行进行赋值。