/*
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 "<