MPI_Recv 覆盖它不应访问的部分内存
Posted
技术标签:
【中文标题】MPI_Recv 覆盖它不应访问的部分内存【英文标题】:MPI_Recv overwrites parts of memory it should not access 【发布时间】:2012-10-24 12:54:49 【问题描述】:在下面的代码中,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_get_count(status,MPI_REAL,n,ierr); print*, n
得到什么——我真的想知道你是否遇到了导致有趣行为的缓冲区溢出......
感谢您的建议!问题显然出在状态声明中,它是一个正常的标量整数。我不知道为什么它在MPI_Recv
中编译,因为MPI_Get_count
的接口检查发现了这个。
很奇怪。我很高兴它抓住了它。 MPI_Recv
可能有一个声明为integer status(*)
的接口,以便它可以接受标量或数组。这样,MPI_STATUS_IGNORE
可能是一个标量......似乎MPI_STATUS_SIZE
足够小以至于没关系,但是,我想图书馆正在努力提高内存效率或其他东西......MPI_Get_count
on另一方面不能接受MPI_STATUS_IGNORE
...
@mgilson、MPI_RECV
(以及任何其他将用户数据缓冲区作为参数的例程)可以将无数种不同的数据类型作为其第一个参数,因此几乎不会出现在模块接口。必须使用特殊标志编译 Open MPI,以便生成此类例程的接口。然后编译需要非常长的时间,并且只涵盖可能的类型的一个相关的小子集。 MPI 3.0 中即将推出一个临时解决方案 - 定义了使用 F2008 的 TYPE(*), DIMENSION(..)
功能的新 F2008 绑定。
F2008 的另一个特性,ASYNCHRONOUS
用于新的 MPI 3.0 接口中的非阻塞调用,如MPI_Isend
。这意味着使用完全符合 F2008 的编译器,可以安全地将数组子节传递给非阻塞调用。
【参考方案1】:
为了以后的访问者,我想我会回答这个问题,即使上面的 cmets 都回答了。
据我所知,如果您的程序运行正常,则无法在调用 MPI_Recv
时更改该参数(“count”)的值。
您的参数status
太小,它应该是一个数组status(MPI_STATUS_SIZE)
,并且您遇到了缓冲区溢出——这通常会导致分段错误,但有时(取决于编译器如何打包内存中的变量),它可能会导致这样的有趣行为。
【讨论】:
这主要发生在堆栈变量被用作调用参数并且没有使用中的指针被覆盖/损坏(调用函数的堆栈帧中的返回地址就是这样的指针)时。 @HristoIliev -- 显然你没有使用我的一些代码;-)。旧的 f77 样式内存管理,其中所有内容都是equivalence
d 在 1 个大数组中,当传递给子例程时会被分区... :)
嘿,现在是 2012 年,我们有 GCC... 和 cookie :)以上是关于MPI_Recv 覆盖它不应访问的部分内存的主要内容,如果未能解决你的问题,请参考以下文章