gmpi.hpp

Go to the documentation of this file.
00001 // $Id: gmpi.hpp,v 1.4 2004/02/22 18:44:46 gottschling Exp $
00002 
00003 #ifndef         _gmpi_include_
00004 #define         _gmpi_include_
00005 
00006 
00007 #include "mpi.h"
00008 #include <utility>
00009 #include <vector>
00010 #include <list>
00011 #include <deque>
00012 // #include <complex>
00013 
00014 
00015 namespace GMPI {
00016 
00017   using std::pair; using std::vector; using std::list; using std::deque;
00018 
00020   inline MPI::Datatype which_mpi_t (char) {return MPI::CHAR;}
00021   // inline MPI::Datatype which_mpi_t (wchar_t) {return MPI::WCHAR;}
00022   // inline MPI::Datatype which_mpi_t (signed char) {return MPI::SIGNED_CHAR;}
00023   inline MPI::Datatype which_mpi_t (signed short) {return MPI::SHORT;}
00024   inline MPI::Datatype which_mpi_t (signed int) {return MPI::INT;}
00025   inline MPI::Datatype which_mpi_t (signed long) {return MPI::LONG;}
00026   inline MPI::Datatype which_mpi_t (unsigned char) {return MPI::UNSIGNED_CHAR;}
00027   inline MPI::Datatype which_mpi_t (unsigned short) {return MPI::UNSIGNED_SHORT;}
00028   inline MPI::Datatype which_mpi_t (unsigned) {return MPI::UNSIGNED;}
00029   // inline MPI::Datatype which_mpi_t (unsigned int) {return MPI::UNSIGNED_INT;}
00030   inline MPI::Datatype which_mpi_t (unsigned long) {return MPI::UNSIGNED_LONG;}
00031   inline MPI::Datatype which_mpi_t (double) {return MPI::DOUBLE;}
00032   inline MPI::Datatype which_mpi_t (long double) {return MPI::LONG_DOUBLE;}
00033   // inline MPI::Datatype which_mpi_t (bool) {return MPI::BOOL;}
00034   // inline MPI::Datatype which_mpi_t (complex<float>) {return MPI::COMPLEX;}
00035   // inline MPI::Datatype which_mpi_t (complex<double>) {return MPI::DOUBLE_COMPLEX;}
00036   // inline MPI::Datatype which_mpi_t (complex<long double>) {return MPI::LONG_DOUBLE_COMPLEX;}
00037   inline MPI::Datatype which_mpi_t (pair<int,int>) {return MPI::TWOINT;}
00038   inline MPI::Datatype which_mpi_t (pair<float,int>) {return MPI::FLOAT_INT;}
00039   inline MPI::Datatype which_mpi_t (pair<double,int>) {return MPI::DOUBLE_INT;}
00040   inline MPI::Datatype which_mpi_t (pair<long double,int>) {return MPI::LONG_DOUBLE_INT;}
00041   inline MPI::Datatype which_mpi_t (pair<short,int>) {return MPI::SHORT_INT;}
00042 
00044   const MPI::Datatype mpi_size_t= which_mpi_t (size_t());
00045 
00046   template <typename Base_t>
00047   class buffer_t {
00048   public:
00049     typedef Base_t       base_t;      
00050     MPI::Datatype        mpi_t;       
00051     const int            base_t_size; 
00052   private:
00053     vector<Base_t>       my_buffer;   // Vector, to use reallocation and copy
00054     mutable size_t       write_pos,   // Written entries (of Base_t)
00055                          read_pos;    // Read entries (of Base_t)
00056     mutable bool         read_write;  // Either read or write, true == read
00057   public:
00059     buffer_t () :  mpi_t (which_mpi_t (Base_t())), 
00060                 base_t_size (sizeof (Base_t)),
00061                 write_pos (0), read_pos (0), read_write (false) {}
00063     buffer_t (size_t n) :  mpi_t (which_mpi_t (Base_t())), 
00064                 base_t_size (sizeof (Base_t)),
00065                 write_pos (0), read_pos (0), read_write (false) {reserve (n);}
00066 
00068     void reserve (size_t n) {
00069       if (read_write) { // change to write
00070         write_pos= 0; my_buffer.resize (n); read_write= false; return; }
00071       if (write_pos+n > my_buffer.size()) my_buffer.resize (write_pos+n);}
00072 
00074     bool empty () const {
00075       return read_pos == write_pos; }
00076 
00078     size_t remaining () const {
00079       return write_pos - read_pos; }
00080 
00082     Base_t read () const {
00083       if (!read_write) { // change to read
00084         read_pos= 0; read_write= true; }
00085       // if (read_pos >= write_pos) throw gmpi_exception ("Read past end");
00086       return my_buffer[read_pos++]; }
00087 
00089     void unread () const {
00090       // if (!read_write) throw gmpi_exception ("Unread in write mode");
00091       // if (read_pos == 0) throw gmpi_exception ("Unread at the beginning");
00092       read_pos--; }
00093       
00095     void write (Base_t output) {
00096       if (read_write) { // change to write
00097         write_pos= 0; my_buffer.resize (1); read_write= false; }
00098       // if (write_pos > my_buffer.size()) throw gmpi_exception ("Written past end");
00099       reserve (1);
00100       my_buffer[write_pos++]= output; }
00101 
00103     void load (Base_t* address, size_t n) const {
00104       if (!read_write) { // change to read
00105         read_pos= 0; read_write= true; }
00106       // if (read_pos+n > write_pos) throw gmpi_exception ("Read past end");
00107       memcpy (address, &my_buffer[read_pos], n * base_t_size);
00108       read_pos+= n; }
00109 
00111     void store (Base_t* address, size_t n) {
00112       if (read_write) { // change to write
00113         write_pos= 0; my_buffer.resize (n); read_write= false; }
00114       reserve (write_pos+n - my_buffer.size());
00115       memcpy (&my_buffer[write_pos], address, n * base_t_size);
00116       write_pos+= n; }
00117 
00119     size_t size () const {return my_buffer.size(); }
00120 
00122     Base_t* address () {return &my_buffer[0]; }
00123 
00125     const Base_t* buffer_address () const {return &my_buffer[0]; }
00126 
00128     void free () {
00129       my_buffer.resize (0); write_pos= read_pos= 0; read_write= false; }      
00130   };
00131 
00133   template <typename Base_t> inline
00134   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, Base_t& input) {
00135     input= buffer.read (); return buffer; }
00136 
00138   template <typename Base_t> inline
00139   buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, const Base_t& output) {
00140     buffer.write (output); return buffer; }
00141 
00143   template <typename Base_t> inline
00144   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, 
00145                                       vector<Base_t>& input) {
00146     int csize= input.size(), n= buffer.remaining();
00147     input.resize (csize + n);
00148     buffer.load (&input[csize], n); 
00149     return buffer; }
00150   
00152   template <typename Base_t> inline
00153   const buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, 
00154                                       const vector<Base_t>& output) {
00155     int n= output.size();
00156     buffer.store (&output[0], n); 
00157     return buffer; }
00158 
00159   // =========== Derived Operators ============================================
00160   
00162   template <typename Base_t, typename Scalar1_t, typename Scalar2_t> inline
00163   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, 
00164                                       pair<Scalar1_t, Scalar2_t>& input) {
00165     buffer >> input.first >> input.second; return buffer; }
00166 
00168   template <typename Base_t, typename Scalar1_t, typename Scalar2_t> inline
00169   buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, 
00170                                       const pair<Scalar1_t, Scalar2_t>& output) {
00171     buffer << output.first << output.second; return buffer; }
00172 
00174   template <typename Base_t, typename Scalar_t> inline
00175   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, 
00176                                       vector<Scalar_t>& input) {
00177     size_t size; buffer >> size;
00178     for (size_t c= 0; c < size; c++) {
00179       Scalar_t scalar; buffer >> scalar; input.push_back (scalar); }
00180     return buffer; }
00181 
00183   template <typename Base_t, typename Scalar_t> inline
00184   buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, 
00185                                 const vector<Scalar_t>& output) {
00186     buffer << output.size(); // Base_t must be large enough for the vector size
00187     for (typename vector<Scalar_t>::const_iterator it= output.begin(), end= output.end(); 
00188          it != end;) buffer << *it++;
00189     return buffer; }
00190 
00192   template <typename Base_t, typename Scalar_t> inline
00193   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, 
00194                                       list<Scalar_t>& input) {
00195     size_t size; buffer >> size;
00196     for (size_t c= 0; c < size; c++) {
00197       Scalar_t scalar; buffer >> scalar; input.push_back (scalar); }
00198     return buffer; }
00199 
00201   template <typename Base_t, typename Scalar_t> inline
00202   buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, 
00203                                 const list<Scalar_t>& output) {
00204     buffer << output.size(); // Base_t must be large enough for the list size
00205     for (typename list<Scalar_t>::const_iterator it= output.begin(), end= output.end(); it != end;)
00206       buffer << *it++;
00207     return buffer; }
00208 
00210   template <typename Base_t, typename Scalar_t> inline
00211   const buffer_t<Base_t>& operator>> (const buffer_t<Base_t>& buffer, 
00212                                       deque<Scalar_t>& input) {
00213     size_t size; buffer >> size;
00214     for (size_t c= 0; c < size; c++) {
00215       Scalar_t scalar; buffer >> scalar; input.push_back (scalar); }
00216     return buffer; }
00217 
00219   template <typename Base_t, typename Scalar_t> inline
00220   buffer_t<Base_t>& operator<< (buffer_t<Base_t>& buffer, 
00221                                 const deque<Scalar_t>& output) {
00222     buffer << output.size(); // Base_t must be large enough for the deque size
00223     for (typename deque<Scalar_t>::const_iterator it= output.begin(), end= output.end(); 
00224          it != end;) buffer << *it++;
00225     return buffer; }
00226 
00227   template <typename Base_t, typename Object_t>
00228   class comm_ref_t {
00229   public:
00230     typedef Base_t                 base_t;
00231     typedef Object_t               object_t;
00232   private:
00233     object_t&                      my_object_ref;
00234   public:
00235     comm_ref_t (object_t& o) : my_object_ref (o) {}
00236     object_t& object_ref() {return my_object_ref; }
00237     const object_t& object_ref() const {return my_object_ref; }
00238   };
00239 
00240   class Comm {
00241   protected:
00242     MPI::Intracomm         my_comm;
00243   public:
00244     Comm (const MPI::Intracomm& mpi_comm) : my_comm (mpi_comm.Dup()) {}
00245 
00246     MPI::Intracomm& mpi_comm_ref () {return my_comm;}
00247     const MPI::Intracomm& mpi_comm_ref () const {return my_comm;}
00248    
00250     template <typename Comm_ref_t>
00251     void Send (const Comm_ref_t& data, int dest, int tag) const;
00252 
00253     template <typename Comm_ref_t>
00254     void Recv (Comm_ref_t& data, int source, int tag, MPI::Status& status) const;
00255 
00256     int Get_size () const {return my_comm.Get_size (); }
00257 
00258     int Get_rank () const {return my_comm.Get_rank (); }
00259   };
00260 
00261   class Intracomm : public Comm {
00262   public:
00263     Intracomm (MPI::Intracomm& mpi_comm) : Comm (mpi_comm) {}
00264     
00265     void Barrier () const {my_comm.Barrier (); }
00266 
00267     template <typename Comm_ref_t>
00268     void Bcast (Comm_ref_t& data, int root) const;
00269 
00270     void Bcast (void* buffer, int count, const MPI::Datatype& datatype, int root) const {
00271       my_comm.Bcast (buffer, count, datatype, root); }
00272 
00273     template <typename Comm_ref_t>
00274     void Reduce (const Comm_ref_t& senddata, Comm_ref_t& recvdata, 
00275                  const MPI::Op& op, int root) const;
00276 
00277     template <typename Comm_ref_t>
00278     void Allreduce (const Comm_ref_t& senddata, Comm_ref_t& recvdata, 
00279                     const MPI::Op& op) const;    
00280 
00281     // template <typename Base_t>
00282     // void Allreduce (const Base_t& senddata, Base_t& recvdata, const MPI::Op& op) const {
00283     //   my_comm.Allreduce (&senddata, &recvdata, 1, which_mpi_t (senddata), op); }
00284 
00285     void Allreduce (const void* sendbuf, void* recvbuf, int count, 
00286                     const MPI::Datatype& datatype, const MPI::Op& op) const {
00287       my_comm.Allreduce (sendbuf, recvbuf, count, datatype, op); }
00288 
00289     void Gather (const void* sendbuf, int sendcount, const MPI::Datatype& sendtype,
00290                  void* recvbuf, int recvcount, const MPI::Datatype& recvtype, int root) const {
00291       my_comm.Gather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root); }
00292   };
00293 
00294 } // namespace GMPI
00295 
00296 #include "gmpi_impl.hpp" // long template implementations
00297 
00298 #endif //       _gmpi_include_
00299 
00300 
00301 
00302 
00303 
00304 

Generated on Wed Mar 11 10:33:11 2009 for angel by  doxygen 1.5.3