2012-12-11 126 views
0

考虑以下几点:Fortran语言/ MPI非阻塞发送

subroutine send_to_friend(a,b,c,request) 
    implicit none 
    include 'mpif.h' !use mpi if you've built the mpif90 bindings... 

    real a,b,c 
    real buff(3) 
    integer tag,dest,ierr,request 

    tag = 50 
    dest = 0 

    buff(1) = a 
    buff(2) = b 
    buff(3) = c 
    call MPI_Isend(buff,3,MPI_REAL,dest,tag,MPI_COMM_WORLD,request,ierr) 
return 
end subroutine send_to_friend 

这可能会不起作用,因为buff会在堆栈上(反正大多数现代编译)放,但将当子程序退出时擦干净。分配数组也没有帮助,因为根据here(第10节),当您退出过程时分配的数组会自动解除分配 - 在C中,这将是内存泄漏(也是不好的)。什么是这样做的正确方法?我应该用save属性声明该数组吗? (C中的static)。这种设计本身是否有缺陷?

+0

是的,我很想说设计本身就存在问题;即使使用'save',如果连续快速调用这个子程序两次会发生什么?您可以使用['MPI_Bsend'](http://www.mcs.anl.gov/research/projects/mpi/www/www/MPI_Bsend.html)和“足够的”用户定义缓冲区空间,并管理缓冲区MPI的问题,但[缓冲发送是邪恶的](http://blogs.cisco.com/performance/top-10-reasons-why-buffered-sends-are-evil/) –

+0

@JonathanDursi - 这就是为什么你返回'请求' - 确保数据在您再次调用之前已经发送。你还应该怎么做这样的事情?当发送数据到'0'时,当前进程有很多事情要做......而且我不想等'0'太忙而无法立即接收消息......是不是全部“isend”的用途是以什么为开头? – mgilson

+0

如果您必须手动处理检查先前的请求以确定是否可以调用此子例程,那么我只是看不到这个子例程的要点。如果你必须做一堆低级的东西才能安全地调用这个子程序,那么你并没有真正抽象出任何东西。也许你已经在代码中有了更高层次的内容,但仅仅看到这个例程很难说。如果你真的想这样做,我只是建议使用bsend(注意:不是ibsend,出于同样的原因)或者将它传递给一个缓冲区并让它安全地处理缓冲。 –

回答

0

SAVE应该没问题(最好与allocatable结合使用),前提是您不会遇到其他问题,这需要Fortran通过copy-in copy-out传递数组,但必须通过引用来完成(不要尝试使用非阻塞MPI发送非连续数据)。

如果在例程中有save变量,如果组合使用MPI/OpenMP,也不要尝试从更多线程运行它。

+0

在OpenMP中使用堆变量作为只读是否安全,还是我的误解? (无论如何,我没有使用OpenMP,所以这只是学术上的好奇心)。另外,你为什么说最好与allocatable结合?(我想过,但是我需要检查它是否已被分配,看起来有点混乱) – mgilson

+0

使用OpenMP,可以使'buff'数组成为线程私有的。 –

+0

因为自动数组不成问题,所以编译时间常量对小事情有好处,指针会损害性能(不是简单的情况)。 –