为啥此代码段错误(在分配期间)与 pgi 而不是英特尔?
Posted
技术标签:
【中文标题】为啥此代码段错误(在分配期间)与 pgi 而不是英特尔?【英文标题】:Why does this code seg fault (during allocation) with pgi but not intel?为什么此代码段错误(在分配期间)与 pgi 而不是英特尔? 【发布时间】:2014-08-11 14:00:05 【问题描述】:此代码在英特尔编译器上运行时有效。但是,当使用 pgi 运行时,它会在列出的子例程中的 * 和 ** 之间出现错误。我正在使用带有-mcmodel-medium 的pgi 编译器。我需要使用 PGI 来开始对这段代码使用 openacc。有什么想法可能是错的吗?提前致谢!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Reading in trajectories from 'md.traj' file
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE READ_INPUT(time_i,time_f,dt,ION_COUNT,x,y,z,lf,l,nsteps)
IMPLICIT NONE
Integer*4, Intent(IN) ::time_i,time_f,dt
Real*4,Intent(OUT),DIMENSION(:,:), Allocatable ::x,y,z
Real*4 ::vx,vy,vz
Real*8, Intent(OUT) ::lf,l
Integer*4 ::time,t,j,nsteps
Integer*4 ::ION_COUNT
Character*100 ::filename
Character*5 ::timezone
Character*6 ::xfiletype
Character*8 ::xcode_version,date
Character*10 ::xcode_name,daytime
Character*20 ::xsim_type
Real*8 ::time_set,aspect(3),ev,ek,ppx,pp(9),rho
write (*,*) '*'
Allocate(x(1:51200,0:nsteps))
Allocate(y(1:51200,0:nsteps))
Allocate(z(1:51200,0:nsteps))
write (*,*) '**'
open(UNIT=20,FILE='md.traj.00007000000.xv4b',status='OLD',form='unformatted',convert='BIG_ENDIAN')
Do 20, time=time_i, time_f, dt
write (*,*) time
write(*,1001) time
1001 format ('md.',1I11.11,'.x4b')
write (filename,1001) time
read(20) xfiletype
read(20) xcode_name, xcode_version
read(20) date,daytime,timezone
read(20) xsim_type
read(20) time_set,rho,aspect(1),aspect(2),aspect(3),ev, ek, ppx, pp, ION_COUNT
!rho=ION_COUNT/(xl(1)*xl(2)*xl(3))
t=(time-time_i)/dt
!在这一行没有分配子程序代码段错误
read (20) (x(j,t),y(j,t),z(j,t),vx,vy,vz, j=1,ION_COUNT)
l=(ION_COUNT/(rho))**(1.0/3.0)
!write (*,*) x(500,5),'in read input'
lf=(2*3.1415)/l
20 continue
RETURN
END SUBROUTINE READ_INPUT
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
这里是主要代码
Program SofQ
Implicit NONE
Integer :: time,time_u,j,i,k,OMP_NUM_THREADS
Integer :: t1,t3,t4,K2
Integer :: dw,t,time1,time2
Real*4 :: sumbin(0:50000)
Real*8 :: f(0:500,0:10000)
Integer :: Q1,Q2,Q3,Q4,Q5,N1,N2,N3,N4,N5,Qcur
Real*4 :: CI,co(0:6537673),si(0:6537673),b(0:6537673)
Real*8 :: dotprod,co_temp,si_temp
Real*4 :: Qavg,zz,qmax,pfrac,nfrac
Complex*16,Allocatable:: q(:,:)
Complex :: sumbin1(0:50000),sumbin2(0:50000)
Double Precision :: yy
Character :: sofq_output,dumb
Parameter (CI=(0,-1))
Real*8 ::rtemp1,rtemp2,rtemp3
Character*5 :: simtype
Integer*4 ::p_start,p_end,nsteps
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Declarations for READ_INPUT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Integer*4 ::time_i,time_f,dt,ION_COUNT
Real*4,Dimension(:,:),Allocatable ::x,y,z
Real*8 ::lf,l
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Declarations for READ_VECTORS
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Integer*4 ::vmax,lines,i_vmax
Integer*4, Dimension(1:6537673) ::rx,ry,rz,mag,degen
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Declarations for COMPUTE_SQ
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Integer*4 ::ions,t2
Real*8, Allocatable ::s(:)
Complex*16,Allocatable ::r(:,:)
open (UNIT=11,File='sqt_n1_gpu.dat')
write (*,*) 'begin'
call system_clock(time1)
dt=20
time_i= 7000000
time_f= 7000500 !7050000
nsteps=(time_f-time_i)/dt
Allocate(x(1:51200,0:nsteps))
Allocate(y(1:51200,0:nsteps))
Allocate(z(1:51200,0:nsteps))
ION_COUNT=51200
qmax=0.6
simtype='pfrac'
! OMP_NUM_THREADS=16
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Parallel Test!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !$OMP PARALLEL
! write (*,*) 'Parallel?'
! !$OMP END PARALLEL
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
CALL READ_INPUT(time_i,time_f,dt,ION_COUNT,x,y,z,lf,l,nsteps)
write (*,*) 'input'
因此,一些评论者询问了子程序内部的重新分配。我这样做是因为首先我在没有第二次分配的情况下尝试了它,并且当它读取第一个 x() 值时在子例程中收到了分段错误。我又试了一次,注释掉子程序中的分配,发现在读取 x() 期间 PGI seg 出现错误,intel 编译器也这样做了。此行在上面用粗体表示。
【问题讨论】:
尝试在 allocate 中使用stat=
参数并在此处报告它返回的内容。
这个 stat= 参数究竟是如何使用的?我尝试将其设置为等于 var 然后写入 var,但它在写入之前会出现故障。我将我尝试过的代码放在原始问题中。
它是如何使用的。你有所有的调试选项和运行时检查吗?错误消息的外观如何?你有回溯吗?你试过 gdb 还是 valgrind?
我对使用调试器不是很熟悉。我在网上找到了这些(-g、-gobt、-Mbounds、-v、-Mlist)并使用了第一个,“-g”返回了 0 内联和一些 .mod 文件,这些文件对我来说相当难以理解,但我可以发布如果它们有用的话。使用运行时检查 -Mbounds 没有返回任何内容。
崩溃时的错误信息是怎样的?
【参考方案1】:
当您将intent(OUT)
用于可分配数组的参数时,数组变量(在您的情况下为x、y 和z)在进入子例程时变为“未分配”。因此,在这种情况下,您必须在开始使用之前将其分配到子例程中。
当您在子例程内部分配可分配数组时,因为它与一个虚拟参数相关联,所以它不会在子例程结束时被释放,就像如果数组是本地数组时会发生的那样。
因此,您可以简单地使用intent(inout)
声明 x、y 和 z(或者什么都不声明,因为在这种情况下,“intent(INOUT)”将具有与不定义意图相同的影响)并且无需分配数组再次在子程序中。或者您可以只在例程内部分配它,而避免在例程外部分配。但我认为,一旦您似乎想在子例程之外使用数组,这是一种不好的做法。
当您使用代码而不在子例程内“分配”时,两个编译器都会“段错误”这一事实是正确的行为,因为在进入子例程时数组将未分配(因为意图(out))。在您在子例程中“再次”分配数组的情况下,PGI“段错误”这一事实似乎是某种编译器错误。在这种情况下,如果您使用 PGI,则在子例程之外进行分配可能是唯一可用的选项。
【讨论】:
它不会变成未定义的,它有一个完美定义的状态——它是未分配的。 感谢@VladimirF。是的,该州的“正确词”是“未分配”。我会更改答案中的单词。 @VladimirF,我的意思是说意图(inout)。感谢您指出。 不抱歉,我的评论有误。intent(inout)
和“未指定意图”是不同的。
是的,我认为现在可以了,也许通过一些格式它会更具可读性,但这取决于你。并不是说 ICE(内部编译器错误)通常意味着编译器崩溃时在编译期间发生错误。这不仅仅是任何编译器错误。以上是关于为啥此代码段错误(在分配期间)与 pgi 而不是英特尔?的主要内容,如果未能解决你的问题,请参考以下文章
使用 fortran PGI 编译器,为啥 real(.true.) 等于“-1.0”而 int(.true.) 等于“-1”?