SkelGIS  3.0
/home/helene/Documents/These/SkelGIS/SkelGIS_Library/SkelGIS_V3/skelgis/util/communications.hpp
Go to the documentation of this file.
00001 /*! \file communications.hpp
00002  *  \brief Definitions of the communication class of SkelGIS. This class is used to make MPI communications.
00003  */
00004 #ifndef COMMUNICATIONS_H
00005 #define COMMUNICATIONS_H
00006 
00007 #include "mpi.h"
00008 #include "mpi_.hpp"
00009 
00010 namespace skelgis{
00011 
00012   //-------------------------------------------------------------------------------
00013   //!  template communication Class 
00014   /*!
00015     This template class defines the MPI initializations, the MPI communications
00016     \tpara T is the type of data to exchange
00017   */
00018   //-------------------------------------------------------------------------------
00019   template<class T> class Communications
00020   //-------------------------------------------------------------------------------
00021   {
00022   public:
00023     //-------------------------------------------------------------------------------
00024     //! used by get borders to make exchanges
00025     /*!
00026       \param toGet is the data to get from mpi process and omp thread
00027       \param toSend is the data to send to mpi process and omp thread
00028       \param size is the size of data to send and recv
00029       \param rank is the mpi rank to exchange with
00030     */
00031     //-------------------------------------------------------------------------------
00032     static void Exchanges(T * toSend, T* toGet,unsigned int size,int rank)
00033     //-------------------------------------------------------------------------------
00034     {
00035       MPI_Status statu;
00036       MPI_Request request;
00037       
00038 #ifdef DEBUG
00039       std::stringstream st;
00040       st<<"Values to give to rank "<<rank<<"\n";
00041       for(int j=0;j<size;j++)
00042         {
00043           st<<toSend[j]<<" ";
00044         }
00045       st<<"\n";
00046       Mpi_::print(st.str());
00047 #endif
00048 
00049       //work for every basic types not for complex types
00050       char * get = new char[size*sizeof(T)];
00051       MPI_Sendrecv(reinterpret_cast<char *>(toSend), size*(sizeof(T)), MPI_BYTE,rank,0,get,size*(sizeof(T)),MPI_BYTE,rank,0,MPI_COMM_WORLD,&statu);
00052       for(int i=0;i<size;i++)
00053           memcpy(&toGet[i], get+i*sizeof(T), sizeof(T));
00054       delete [] get;
00055 
00056 #ifdef DEBUG
00057       std::stringstream st2;
00058       st2<<"values given by rank "<<rank<<"\n";
00059       for(int j=0;j<size;j++)
00060         {
00061           st2<<toGet[j]<<" ";
00062         }
00063       st2<<"\n";
00064       Mpi_::print(st2.str());
00065 #endif
00066     }
00067     //-------------------------------------------------------------------------------
00068 
00069     
00070     //-------------------------------------------------------------------------------
00071     //for DDAG construction of an object needed
00072     //an instance of the object is constructed for each DPMap (nodes or edges)
00073     //this object manage non blocking MPI exchanges and received values as a MPI_BYTE type
00074     //-------------------------------------------------------------------------------
00075 
00076     /*!< requests_s is the list of requests for send communications (one for each processor) */
00077     MPI_Request * requests_s;
00078     /*!< requests_s is the list of requests for receive communications (one for each processor) */
00079     MPI_Request * requests_r;
00080     /*!< requests_s is the list of status for send communications (one for each processor) */
00081     MPI_Status * status_s;
00082     /*!< requests_s is the list of status for receive communications (one for each processor) */
00083     MPI_Status * status_r;
00084     char ** get;
00085 
00086     //-------------------------------------------------------------------------------
00087     //! constructor
00088     /*!
00089     */
00090     //-------------------------------------------------------------------------------
00091     Communications()
00092     //-------------------------------------------------------------------------------
00093     {
00094       requests_s = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00095       requests_r = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00096       status_s = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00097       status_r = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00098       get = (char **)calloc(Mpi_::mpi_nb,sizeof(char*));
00099     }
00100     //-------------------------------------------------------------------------------
00101     //! destructor
00102     /*!
00103     */
00104     //-------------------------------------------------------------------------------
00105     ~Communications()
00106     //-------------------------------------------------------------------------------
00107     {
00108       free(requests_s);
00109       free(requests_r);
00110       free(status_s);
00111       free(status_r);
00112       free(get);
00113     }
00114     //-------------------------------------------------------------------------------
00115     //! A non blocking MPI send is initialized
00116     /*!
00117       \param buf is the sending buffer
00118       \param count is the number of elements in the buffer
00119       \param dest is the destination processor
00120       \return the return value of the MPI_Isend function
00121     */
00122     //-------------------------------------------------------------------------------
00123     inline int ISend(T *buf, int count, int dest)
00124     //-------------------------------------------------------------------------------
00125     {
00126       return  MPI_Isend(reinterpret_cast<char *>(buf), count*(sizeof(T)), MPI_BYTE, dest, 0, MPI_COMM_WORLD, &(requests_s[dest]));
00127     }
00128     //-------------------------------------------------------------------------------
00129     //! A non blocking MPI receive is initialized
00130     /*!
00131       \param count is the number of elements to receive
00132       \param source is the source processor
00133       \return the return value of the MPI_Irecv function
00134     */
00135     //-------------------------------------------------------------------------------
00136     int IRecv(int count, int source)
00137     //-------------------------------------------------------------------------------
00138     {
00139       get[source] = new char[count*sizeof(T)];
00140       return MPI_Irecv(get[source], count*(sizeof(T)), MPI_BYTE, source, 0, MPI_COMM_WORLD, &(requests_r[source]));
00141     }
00142     //-------------------------------------------------------------------------------
00143     //! A MPI wait call to wait for the send exchange with a precise processor
00144     /*!
00145       \param dest is the destination processor the send is waiting
00146       \return the return value of the MPI_Wait function
00147     */
00148     //-------------------------------------------------------------------------------
00149     inline int Wait_s(int dest)
00150     //-------------------------------------------------------------------------------
00151     {
00152       return MPI_Wait(&(requests_s[dest]), &(status_s[dest]));
00153     }
00154     //-------------------------------------------------------------------------------
00155     //! A MPI wait call to wait for the send exchange with a precise processor
00156     /*!
00157       \param dest is the destination processor the send is waiting
00158       \return the return value of the MPI_Wait function
00159     */
00160     //-------------------------------------------------------------------------------
00161     int Wait_r(T * toRecv, int src,int count)
00162     //-------------------------------------------------------------------------------
00163     {
00164       int ret = MPI_Wait(&(requests_r[src]), &(status_r[src]));
00165       for(int i=0;i<count;i++)
00166         memcpy(&toRecv[i], get[src]+i*sizeof(T), sizeof(T));
00167 
00168       delete [] get[src];
00169 
00170       return ret;
00171     }
00172     //-------------------------------------------------------------------------------
00173   };
00174   //-------------------------------------------------------------------------------
00175 
00176 
00177   //-------------------------------------------------------------------------------
00178   //!  template communicationInOut Class 
00179   /*!
00180     This template class defines the MPI initializations, the MPI communications
00181     \tpara T is the type of data to exchange
00182   */
00183   //-------------------------------------------------------------------------------
00184   template<class T> class CommunicationsInOut
00185   //-------------------------------------------------------------------------------
00186   {
00187   public:
00188     //-------------------------------------------------------------------------------
00189     //for DDAG construction of an object needed
00190     //an instance of the object is constructed for each DPMap (nodes or edges) advanced on pointers
00191     //this object manage non blocking MPI exchanges and received values as a MPI_BYTE type
00192     //-------------------------------------------------------------------------------
00193 
00194     /*!< requests_s is the list of requests for send communications (one for each processor) */
00195     MPI_Request * requests_s_out;
00196     MPI_Request * requests_s_in;
00197     /*!< requests_s is the list of requests for receive communications (one for each processor) */
00198     MPI_Request * requests_r_out;
00199     MPI_Request * requests_r_in;
00200     /*!< requests_s is the list of status for send communications (one for each processor) */
00201     MPI_Status * status_s_out;
00202     MPI_Status * status_s_in;
00203     /*!< requests_s is the list of status for receive communications (one for each processor) */
00204     MPI_Status * status_r_out;
00205     MPI_Status * status_r_in;
00206     char ** get_out;
00207     char ** get_in;
00208 
00209     //-------------------------------------------------------------------------------
00210     //! constructor
00211     /*!
00212     */
00213     //-------------------------------------------------------------------------------
00214     CommunicationsInOut()
00215     //-------------------------------------------------------------------------------
00216     {
00217       requests_s_out = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00218       requests_s_in = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00219       requests_r_out = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00220       requests_r_in = (MPI_Request *)calloc(Mpi_::mpi_nb,sizeof(MPI_Request));
00221       status_s_out = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00222       status_s_in = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00223       status_r_out = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00224       status_r_in = (MPI_Status *)calloc(Mpi_::mpi_nb,sizeof(MPI_Status));
00225       get_out = (char **)calloc(Mpi_::mpi_nb,sizeof(char*));
00226       get_in = (char **)calloc(Mpi_::mpi_nb,sizeof(char*));
00227     }
00228     //-------------------------------------------------------------------------------
00229     //! destructor
00230     /*!
00231     */
00232     //-------------------------------------------------------------------------------
00233     ~CommunicationsInOut()
00234     //-------------------------------------------------------------------------------
00235     {
00236       free(requests_s_out);
00237       free(requests_s_in);
00238       free(requests_r_out);
00239       free(requests_r_in);
00240       free(status_s_out);
00241       free(status_s_in);
00242       free(status_r_out);
00243       free(status_r_in);
00244       free(get_out);
00245       free(get_in);
00246     }
00247     //-------------------------------------------------------------------------------
00248     //! A non blocking MPI send is initialized
00249     /*!
00250       \param buf is the sending buffer out of another processor
00251       \param count is the number of elements in the buffer
00252       \param dest is the destination processor
00253       \return the return value of the MPI_Isend function
00254     */
00255     //-------------------------------------------------------------------------------
00256     inline int ISendOut(T *bufOut, int count, int dest)
00257     //-------------------------------------------------------------------------------
00258     {
00259       return  MPI_Isend(reinterpret_cast<char *>(bufOut), count*(sizeof(T)), MPI_BYTE, dest, 0, MPI_COMM_WORLD, &(requests_s_out[dest]));
00260     }
00261     //-------------------------------------------------------------------------------
00262     //! A non blocking MPI send is initialized
00263     /*!
00264       \param buf is the sending buffer in another processor
00265       \param count is the number of elements in the buffer
00266       \param dest is the destination processor
00267       \return the return value of the MPI_Isend function
00268     */
00269     //-------------------------------------------------------------------------------
00270     inline int ISendIn(T *bufIn, int count, int dest)
00271     //-------------------------------------------------------------------------------
00272     {
00273       return  MPI_Isend(reinterpret_cast<char *>(bufIn), count*(sizeof(T)), MPI_BYTE, dest, 0, MPI_COMM_WORLD, &(requests_s_in[dest]));
00274     }
00275     //-------------------------------------------------------------------------------
00276     //! A non blocking MPI receive is initialized
00277     /*!
00278       \param count is the number of elements to receive from an out edge
00279       \param source is the source processor
00280       \return the return value of the MPI_Irecv function
00281     */
00282     //-------------------------------------------------------------------------------
00283     int IRecvOut(int count, int source)
00284     //-------------------------------------------------------------------------------
00285     {
00286       get_out[source] = new char[count*sizeof(T)];
00287       return MPI_Irecv(get_out[source], count*(sizeof(T)), MPI_BYTE, source, 0, MPI_COMM_WORLD, &(requests_r_out[source]));
00288     }
00289     //-------------------------------------------------------------------------------
00290     //! A non blocking MPI receive is initialized
00291     /*!
00292       \param count is the number of elements to receive from an in edge
00293       \param source is the source processor
00294       \return the return value of the MPI_Irecv function
00295     */
00296     //-------------------------------------------------------------------------------
00297     int IRecvIn(int count, int source)
00298     //-------------------------------------------------------------------------------
00299     {
00300       get_in[source] = new char[count*sizeof(T)];
00301       return MPI_Irecv(get_in[source], count*(sizeof(T)), MPI_BYTE, source, 0, MPI_COMM_WORLD, &(requests_r_in[source]));
00302     }
00303     //-------------------------------------------------------------------------------
00304     //! A MPI wait call to wait for the send exchange with a precise processor
00305     /*!
00306       \param dest is the destination processor the send is waiting
00307       \return the return value of the MPI_Wait function
00308     */
00309     //-------------------------------------------------------------------------------
00310     inline int Wait_sOut(int dest)
00311     //-------------------------------------------------------------------------------
00312     {
00313       return MPI_Wait(&(requests_s_out[dest]), &(status_s_out[dest]));
00314     }
00315     //-------------------------------------------------------------------------------
00316     //! A MPI wait call to wait for the send exchange with a precise processor
00317     /*!
00318       \param dest is the destination processor the send is waiting
00319       \return the return value of the MPI_Wait function
00320     */
00321     //-------------------------------------------------------------------------------
00322     inline int Wait_sIn(int dest)
00323     //-------------------------------------------------------------------------------
00324     {
00325       return MPI_Wait(&(requests_s_in[dest]), &(status_s_in[dest]));
00326     }
00327     //-------------------------------------------------------------------------------
00328     //! A MPI wait call to wait for the send exchange with a precise processor
00329     /*!
00330       \param dest is the destination processor the send is waiting
00331       \return the return value of the MPI_Wait function
00332     */
00333     //-------------------------------------------------------------------------------
00334     int Wait_rOut(T * toRecvOut, int src,int count)
00335     //-------------------------------------------------------------------------------
00336     {
00337       int ret = MPI_Wait(&(requests_r_out[src]), &(status_r_out[src]));
00338       for(int i=0;i<count;i++)
00339         memcpy(&toRecvOut[i], get_out[src]+i*sizeof(T), sizeof(T));
00340 
00341       delete [] get_out[src];
00342 
00343       return ret;
00344     }
00345     //-------------------------------------------------------------------------------
00346     //! A MPI wait call to wait for the send exchange with a precise processor
00347     /*!
00348       \param dest is the destination processor the send is waiting
00349       \return the return value of the MPI_Wait function
00350     */
00351     //-------------------------------------------------------------------------------
00352     int Wait_rIn(T * toRecvIn, int src,int count)
00353     //-------------------------------------------------------------------------------
00354     {
00355       int ret = MPI_Wait(&(requests_r_in[src]), &(status_r_in[src]));
00356       for(int i=0;i<count;i++)
00357         memcpy(&toRecvIn[i], get_in[src]+i*sizeof(T), sizeof(T));
00358 
00359       delete [] get_in[src];
00360 
00361       return ret;
00362     }
00363     //-------------------------------------------------------------------------------
00364   };
00365   //-------------------------------------------------------------------------------
00366 }
00367 
00368 #endif
00369 
 All Classes Files Functions Variables Defines