ESyS-Particle  4.0.1
comm.hpp
00001 
00002 //                                                         //
00003 // Copyright (c) 2003-2011 by The University of Queensland //
00004 // Earth Systems Science Computational Centre (ESSCC)      //
00005 // http://www.uq.edu.au/esscc                              //
00006 //                                                         //
00007 // Primary Business: Brisbane, Queensland, Australia       //
00008 // Licensed under the Open Software License version 3.0    //
00009 // http://www.opensource.org/licenses/osl-3.0.php          //
00010 //                                                         //
00012 
00013 
00014 //--- point to point communication primitives for TML_Comm ---
00015 #include "tml/message/packed_message.h"
00016 
00017 //--- STL ---
00018 #include <map>
00019 using std::map;
00020 
00030 template <typename T> 
00031 void TML_Comm::send_array(T* data,int ndata,int dest,int tag)
00032 {
00033   MPI_Send(data,ndata,GetType(*data),dest,tag,m_comm);
00034 }
00035 
00045 template <typename T> 
00046 void TML_Comm::receive_array(T* data,int ndata,int source,int tag)
00047 {
00048   MPI_Recv(data,ndata,GetType(*data),source,tag,m_comm,&m_status);
00049 }
00050 
00063 template <typename T,typename P> 
00064 void TML_Comm::sendrecv_array(T* send_data,int send_count,P* recv_data,int recv_count,int dest,int source,int tag)
00065 {
00066   MPI_Sendrecv(send_data,send_count,GetType(*send_data),dest,tag,recv_data,recv_count,GetType(*recv_data),source,tag,m_comm,&m_status);
00067 }
00068 
00076 template <typename T> 
00077 void TML_Comm::send(T data,int dest,int tag)
00078 {
00079   MPI_Send(&data,1,GetType(data),dest,tag,m_comm);
00080 }
00081 
00082 
00091 template <typename T> 
00092 void TML_Comm::receive(T& data,int source ,int tag)
00093 {
00094   MPI_Recv(&data,1,GetType(data),source,tag,m_comm,&m_status);
00095 }
00096 template <typename T,typename P> 
00107 void TML_Comm::sendrecv(T send_data,P& recv_data,int dest,int source,int tag)
00108 {
00109   MPI_Sendrecv(&send_data,1,GetType(send_data),dest,tag,&recv_data,1,GetType(recv_data),source,tag,m_comm,&m_status);
00110 }
00111 
00119 template <typename T> 
00120 void  TML_Comm::send_cont(const T& data, int dest, int tag)
00121 {
00122   int data_size=data.size();
00123 
00124   // setup buffer
00125   typename T::value_type *buffer=new typename T::value_type[data_size];
00126 
00127   // put data into buffer
00128   int count=0;
00129   
00130   for(typename T::const_iterator iter=data.begin();
00131       iter!=data.end();
00132       iter++){
00133     void* buf=reinterpret_cast<void*>(&(buffer[count])); // get memory adress for buffer element
00134     new(buf)(typename T::value_type)(*iter); // initialize object at this adress
00135     // the placement new stuff (see Stroustrup, p.255ff) is necessary
00136     // because assignment buffer[count]=(*iter) doesn't work if the 
00137     // T::value_type contains constant member data. Initialization by 
00138     // calling the copy constructor directly doesn't work for builtin
00139     // types
00140     count++;
00141   }
00142 
00143   //send size
00144   send(data_size,dest,tag);
00145 
00146   //send data
00147   send_array(buffer,data_size,dest,tag+1024);
00148 
00149   // clean up
00150   delete [] buffer;
00151 }
00152 
00162 template <typename T> 
00163 void TML_Comm::receive_cont(T& data,int source,int tag)
00164 {
00165   int data_size;
00166 
00167   //get size
00168   receive(data_size,source,tag);
00169   // setup recv buffer
00170   typename T::value_type *buffer=new typename T::value_type[data_size];
00171 
00172   //get data
00173   receive_array(buffer,data_size,source,tag+1024);
00174   // insert into container
00175   for(int i=0;i<data_size;i++){
00176     data.insert(data.end(),buffer[i]);
00177   }
00178   delete [] buffer;
00179 }
00180 
00181 
00191 template <typename T,typename P> 
00192 void TML_Comm::sendrecv_cont(T send_data,P& recv_data,int dest,int source,int tag)
00193 {
00194   int send_count=send_data.size();
00195   int recv_count;
00196 
00197   // setup send buffer
00198   typename T::value_type *send_buffer=new typename T::value_type[send_count];
00199 
00200   // put data into send buffer
00201   int count=0;
00202   for(typename T::const_iterator iter=send_data.begin();
00203       iter!=send_data.end();
00204       iter++){
00205     void* buf=reinterpret_cast<void*>(&(send_buffer[count])); // get memory adress for buffer element
00206     new(buf)(typename T::value_type)(*iter); // initialize object at this adress (see send_cont)
00207     count++;
00208   }
00209 
00210   //send/receive size
00211   sendrecv(send_count,recv_count,dest,source,tag);
00212   // check for recv from Null process -> set recv_count to 0 if so
00213   if(source==MPI_PROC_NULL){
00214     recv_count=0;
00215   }
00216 
00217   // setup recv buffer
00218   typename T::value_type *recv_buffer=new typename T::value_type[recv_count];
00219 
00220   //send/receive data
00221   sendrecv_array(send_buffer,send_count,recv_buffer,recv_count,dest,source,tag+1024);
00222 
00223   // insert into container
00224   for(int i=0;i<recv_count;i++){
00225     recv_data.insert(recv_data.end(),recv_buffer[i]);
00226   }
00227 
00228   delete [] send_buffer;
00229   delete [] recv_buffer;
00230 }
00231 
00240 template <typename T> 
00241 void TML_Comm::sendrecv_cont_replace(T& data,int dest,int source,int tag)
00242 {
00243   int send_count=data.size();
00244   int recv_count;
00245 
00246   // setup send buffer
00247   typename T::value_type *send_buffer=new typename T::value_type[send_count];
00248 
00249   // put data into send buffer
00250   int count=0;
00251   for(typename T::const_iterator iter=data.begin();
00252       iter!=data.end();
00253       iter++){
00254     void* buf=reinterpret_cast<void*>(&(send_buffer[count])); // get memory adress for buffer element
00255     new(buf)(typename T::value_type)(*iter); // initialize object at this adress
00256     count++;
00257   }
00258 
00259   //send/receive size
00260   sendrecv(send_count,recv_count,dest,source,tag);
00261   // check for recv from Null process -> set recv_count to 0 if so
00262   if(source==MPI_PROC_NULL){
00263     recv_count=0;
00264   }
00265 
00266   // setup recv buffer
00267   typename T::value_type *recv_buffer=new typename T::value_type[recv_count];
00268 
00269   //send/receive data
00270   sendrecv_array(send_buffer,send_count,recv_buffer,recv_count,dest,source,tag+1024);
00271 
00272   // replace data
00273   data.erase(data.begin(),data.end());
00274     // insert into container
00275   for(int i=0;i<recv_count;i++){
00276     data.insert(data.end(),recv_buffer[i]);
00277   }
00278 
00279 
00280   delete [] send_buffer;
00281   delete [] recv_buffer;
00282 }
00283 
00293 template <typename T> 
00294 void TML_Comm::send_cont_packed(T data, int dest ,bool checked ,int tag)
00295 {
00296   TML_Packed_Message* msg=new TML_Packed_Message(m_comm);
00297   int nb_data=data.size();
00298   
00299   msg->pack(nb_data); // pack number of items first
00300   // pack data
00301   for(typename T::const_iterator iter=data.begin();
00302       iter!=data.end();
00303       iter++){
00304     msg->pack(*iter);
00305   }
00306 
00307   //send size
00308   send(msg->size(),dest,tag);
00309 
00310   //send data
00311   send_array(msg->buffer(),msg->size(),dest,tag+1024);
00312   
00313   delete msg;
00314 }
00315 
00325 template <typename T> 
00326 void TML_Comm::receive_cont_packed(T& data,int source,bool checked,int tag)
00327 {
00328   int msg_size; // total size of the message
00329   int nb_data;  // number of data (i.e. the expected data.size())
00330 
00331   //get size
00332   receive(msg_size,source,tag);
00333 
00334   TML_Packed_Message* msg=new TML_Packed_Message(m_comm,msg_size);
00335 
00336   //get data
00337   receive_array(msg->buffer(),msg_size,source,tag+1024);
00338 
00339   // extract nuber of items
00340   nb_data=msg->pop_int();
00341 
00342   // unpack data
00343   for(int i=0;i<nb_data;i++){
00344     typename T::value_type tv;
00345     msg->unpack(tv);
00346     data.insert(data.end(),tv);
00347   }
00348   delete msg;
00349 }
00350 
00361 template <typename T,typename P> 
00362 void TML_Comm::sendrecv_cont_packed(T send_data, P& recv_data, int dest, int source, bool checked,int tag)
00363 {
00364   TML_Packed_Message* send_msg=new TML_Packed_Message(m_comm);
00365 
00366   int send_nb_data=send_data.size();
00367   int send_msg_size;
00368   int recv_nb_data;
00369   int recv_msg_size; 
00370 
00371   send_msg->pack(send_nb_data); // pack number of items first
00372   // pack data
00373   for(typename T::const_iterator iter=send_data.begin();
00374       iter!=send_data.end();
00375       iter++){
00376     send_msg->pack(*iter);
00377   }
00378   send_msg_size=send_msg->size();
00379    
00380   //send/receive size
00381   sendrecv(send_msg_size,recv_msg_size,dest,source,tag);
00382   // check for recv from Null process -> set recv_count to 0 if so
00383   if(source==MPI_PROC_NULL){
00384     recv_msg_size=0;
00385   }
00386 
00387   // setup receive message 
00388   TML_Packed_Message* recv_msg=new TML_Packed_Message(m_comm,recv_msg_size);
00389 
00390   //send/receive data
00391   sendrecv_array(send_msg->buffer(),send_msg_size,recv_msg->buffer(),recv_msg_size,dest,source,tag+1024);
00392 
00393   if(source!=MPI_PROC_NULL){ // if the source exists
00394     // extract nuber of items
00395     recv_nb_data=recv_msg->pop_int();
00396 
00397     // unpack data
00398     typename T::value_type tv;
00399     for(int i=0;i<recv_nb_data;i++){
00400       recv_msg->unpack(tv);
00401       recv_data.insert(recv_data.end(),tv);
00402     }
00403   }
00404   delete send_msg;
00405   delete recv_msg;
00406 }
00407 
00417 template <typename T> 
00418 void TML_Comm::sendrecv_cont_packed_replace(T& data, int dest, int source, bool checked,int tag)
00419 {
00420   TML_Packed_Message* send_msg=new TML_Packed_Message(m_comm);
00421 
00422   int send_nb_data=data.size();
00423   int send_msg_size;
00424   int recv_nb_data;
00425   int recv_msg_size; 
00426 
00427   send_msg->pack(send_nb_data); // pack number of items first
00428   // pack data
00429   for(typename T::const_iterator iter=data.begin();
00430       iter!=data.end();
00431       iter++){
00432     send_msg->pack(*iter);
00433   }
00434   send_msg_size=send_msg->size();
00435    
00436   //send/receive size
00437   sendrecv(send_msg_size,recv_msg_size,dest,source,tag);
00438   // check for recv from Null process -> set recv_count to 0 if so
00439   if(source==MPI_PROC_NULL){
00440     recv_msg_size=0;
00441   }
00442 
00443   // setup receive message 
00444   TML_Packed_Message* recv_msg=new TML_Packed_Message(m_comm,recv_msg_size);
00445 
00446   //send/receive data
00447   sendrecv_array(send_msg->buffer(),send_msg_size,recv_msg->buffer(),recv_msg_size,dest,source,tag+1024);
00448 
00449   // extract nuber of items
00450   recv_nb_data=recv_msg->pop_int();
00451 
00452   // replace data
00453   data.erase(data.begin(),data.end());
00454   for(int i=0;i<recv_nb_data;i++){
00455     typename T::value_type tv;
00456     recv_msg->unpack(tv);
00457     data.insert(data.end(),tv);
00458   }
00459 
00460   delete send_msg;
00461   delete recv_msg;
00462 }
00463