/* Ray Copyright (C) 2010 Sébastien Boisvert http://DeNovoAssembler.SourceForge.Net/ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You have received a copy of the GNU General Public License along with this program (COPYING). see */ #include #include #include /* * send messages, */ void MessagesHandler::sendMessages(StaticVector*outbox,int source){ for(int i=0;i<(int)outbox->size();i++){ Message*aMessage=((*outbox)[i]); #ifdef ASSERT int destination=aMessage->getDestination(); assert(destination>=0); #endif MPI_Request request; // MPI_Issend // Synchronous nonblocking. Note that a Wait/Test will complete only when the matching receive is posted #ifdef ASSERT assert(!(aMessage->getBuffer()==NULL && aMessage->getCount()>0)); #endif #ifndef ASSERT MPI_Isend(aMessage->getBuffer(),aMessage->getCount(),aMessage->getMPIDatatype(),aMessage->getDestination(),aMessage->getTag(),MPI_COMM_WORLD,&request); #else int value=MPI_Isend(aMessage->getBuffer(),aMessage->getCount(),aMessage->getMPIDatatype(),aMessage->getDestination(),aMessage->getTag(),MPI_COMM_WORLD,&request); assert(value==MPI_SUCCESS); #endif MPI_Request_free(&request); #ifdef ASSERT assert(request==MPI_REQUEST_NULL); #endif } outbox->clear(); } /* * receiveMessages is implemented as recommanded by Mr. George Bosilca from the University of Tennessee (via the Open-MPI mailing list) De: George Bosilca Reply-to: Open MPI Developers À: Open MPI Developers Sujet: Re: [OMPI devel] Simple program (103 lines) makes Open-1.4.3 hang Date: 2010-11-23 18:03:04 If you know the max size of the receives I would take a different approach. Post few persistent receives, and manage them in a circular buffer. Instead of doing an MPI_Iprobe, use MPI_Test on the current head of your circular buffer. Once you use the data related to the receive, just do an MPI_Start on your request. This approach will minimize the unexpected messages, and drain the connections faster. Moreover, at the end it is very easy to MPI_Cancel all the receives not yet matched. george. */ void MessagesHandler::receiveMessages(StaticVector*inbox,RingAllocator*inboxAllocator,int destination){ int flag; MPI_Status status; MPI_Test(m_ring+m_head,&flag,&status); if(flag){ // get the length of the message // it is not necessary the same as the one posted with MPI_Recv_init // that one was a lower bound int tag=status.MPI_TAG; int source=status.MPI_SOURCE; int length; MPI_Get_count(&status,MPI_UNSIGNED_LONG_LONG,&length); u64*filledBuffer=(u64*)m_buffers+m_head*MPI_BTL_SM_EAGER_LIMIT/sizeof(u64); // copy it in a safe buffer u64*incoming=(u64*)inboxAllocator->allocate(length*sizeof(u64)); for(int i=0;ipush_back(aMessage); m_receivedMessages[source]++; // increment the head m_head++; if(m_head==m_ringSize){ m_head=0; } } } void MessagesHandler::showStats(){ cout<<"Rank "<