SkelGIS
3.0
|
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