Fortran MPI_Recv会覆盖它不应该访问的部分内存
在下面的代码中,Fortran MPI_Recv会覆盖它不应该访问的部分内存,fortran,mpi,Fortran,Mpi,在下面的代码中,xysize的值会发生更改,如果我没有将其声明为参数(通常我不能这样做)。只有在gfortran 4.7.2和OpenMPI 1.6中进行了O2等优化后,才会出现这种情况。怎么可能呢?我找不到从mpi.mod导入的确切接口,但C原型明确指出,count是按值传递的,因此它不能更改 write(*,*) im,"receiving from",image_index([iim,jim,kim+1]),"size",& size(D%A(D%starti
xysize
的值会发生更改,如果我没有将其声明为参数(通常我不能这样做)。只有在gfortran 4.7.2和OpenMPI 1.6中进行了O2等优化后,才会出现这种情况。怎么可能呢?我找不到从mpi.mod
导入的确切接口,但C原型明确指出,count
是按值传递的,因此它不能更改
write(*,*) im,"receiving from",image_index([iim,jim,kim+1]),"size",&
size(D%A(D%starti:D%endi,D%startj:D%endj,D%endk)),xysize
call MPI_RECV(D%A(D%starti:D%endi,D%startj:D%endj,D%endk+1),xysize , MPI_REAL, image_index([iim,jim,kim+1])-1,&
5000, comm, status, ierr)
write(*,*) im,"received size",&
size(D%A(D%starti:D%endi,D%startj:D%endj,D%endk)),xysize
输出:
1 receiving from 2 size 4096 4096
1 received size 4096 5000
为了将来的访客,我想我会回答这个问题,尽管上面的评论中已经给出了答案 据我所知,如果程序运行正常,则不能在调用
MPI\u Recv
时更改该参数(“count”)的值
您的参数
status
太小,它应该是一个数组status(MPI\u status\u SIZE)
,并且您会遇到缓冲区溢出——这通常会导致分段错误,但有时(取决于编译器如何在内存中打包变量),这可能会导致像这样有趣的行为。为了未来的访问者,我想我会回答这个问题,尽管上面的评论中已经给出了答案
据我所知,如果程序运行正常,则不能在调用MPI\u Recv
时更改该参数(“count”)的值
您的参数
status
太小,它应该是一个数组status(MPI\u status\u SIZE)
,并且您会遇到缓冲区溢出——这通常会导致分段错误,但有时(取决于编译器如何在内存中打包变量),它会导致类似这样的有趣行为。出于好奇,从mpi\u get\u count(状态、mpi\u REAL、n、ierr)中可以得到什么;print*,n
——我真的很想知道是否缓冲区溢出导致了有趣的行为……感谢您的建议!问题显然出在status中的声明中,它是一个普通的标量整数。我不知道为什么它是在MPI\u Recv
中编译的,因为MPI\u Get\u count
的接口检查捕捉到了这一点。我很高兴它抓住了它MPI_Recv
可以将接口声明为integer status(*)
,以便它可以接受标量或数组。这样,MPI\u STATUS\u IGNORE
就可以是一个标量。。。似乎MPI\u STATUS\u SIZE
足够小,这无关紧要,但是,我想这个库正在努力提高内存效率或者其他什么<另一方面,code>MPI\u Get\u count不能接受MPI\u STATUS\u IGNORE
。@mgilson,MPI\u RECV
(以及任何其他将用户数据缓冲区作为参数的例程)可以将无数不同的数据类型作为其第一个参数,因此在模块接口中几乎不存在。为了生成这些例程的接口,必须编译带有特殊标志的openmpi。然后,它需要花费很长的时间来编译,并且只涉及可能的类型的一个相对较小的子集。MPI 3.0中提供了一个临时解决方案-定义了新的F2008绑定,它们使用F2008的类型(*)、维度(…)
功能。另外,F2008的另一个功能,异步
用于非阻塞调用的新MPI 3.0接口,如MPI Isend
。这意味着在palce中使用完全兼容F2008的编译器,可以安全地将数组子部分传递给非阻塞调用;print*,n——我真的很想知道是否缓冲区溢出导致了有趣的行为……感谢您的建议!问题显然出在status中的声明中,它是一个普通的标量整数。我不知道为什么它是在MPI\u Recv
中编译的,因为MPI\u Get\u count
的接口检查捕捉到了这一点。我很高兴它抓住了它MPI_Recv
可以将接口声明为integer status(*)
,以便它可以接受标量或数组。这样,MPI\u STATUS\u IGNORE
就可以是一个标量。。。似乎MPI\u STATUS\u SIZE
足够小,这无关紧要,但是,我想这个库正在努力提高内存效率或者其他什么<另一方面,code>MPI\u Get\u count不能接受MPI\u STATUS\u IGNORE
。@mgilson,MPI\u RECV
(以及任何其他将用户数据缓冲区作为参数的例程)可以将无数不同的数据类型作为其第一个参数,因此在模块接口中几乎不存在。为了生成这些例程的接口,必须编译带有特殊标志的openmpi。然后,它需要花费很长的时间来编译,并且只涉及可能的类型的一个相对较小的子集。MPI 3.0中提供了一个临时解决方案-定义了新的F2008绑定,它们使用F2008的类型(*)、维度(…)
功能。另外,F2008的另一个功能,异步
用于非阻塞调用的新MPI 3.0接口,如MPI Isend
。这意味着在palce中使用完全兼容F2008的编译器,可以安全地将数组子部分传递给非阻塞调用。这通常发生在堆栈变量用作调用参数且使用中的指针未被覆盖/损坏时(调用函数堆栈帧中的返回地址就是这样的指针).@HristoIliev——很明显,你没有使用过我的一些代码;-)。旧的f77风格的内存管理,其中所有内容都是等价的
d,在一个大数组中,当传递给子例程时,该数组将被分区…:)嘿,现在是2012年,我们像GCC一样。。。和cookies:)这通常发生在堆栈变量用作调用参数并且使用中的指针未被覆盖/损坏(返回值)时