ExaFMM 1
Fast-multipole Method for exascale systems
include/mympi.h
Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2011 by Rio Yokota, Simon Layton, Lorena Barba
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 #ifndef mympi_h
00023 #define mympi_h
00024 #include <mpi.h>
00025 #include <typeinfo>
00026 #include "types.h"
00027 
00028 //! Custom MPI utilities
00029 class MyMPI {
00030 protected:
00031   const int WAIT;                                               //!< Waiting time between output of different ranks
00032   int       MPISIZES;                                           //!< Number of MPI processes for split communicator
00033   int       MPIRANKS;                                           //!< Rank of current MPI process for split communicator
00034 public:
00035 //! Constructor, initialize WAIT time
00036   MyMPI() : WAIT(100) {                                         // Constructor, initialize WAIT time
00037     int argc(0);                                                // Dummy argument count
00038     char **argv;                                                // Dummy argument value
00039     int ExternalMPI;                                            // Flag for external MPI call
00040     MPI_Initialized(&ExternalMPI);                              // Check if MPI_Init has been called
00041     if(!ExternalMPI) MPI_Init(&argc,&argv);                     // Initialize MPI communicator
00042     MPI_Comm_size(MPI_COMM_WORLD,&MPISIZE);                     // Get number of MPI processes
00043     MPI_Comm_rank(MPI_COMM_WORLD,&MPIRANK);                     // Get rank of current MPI process
00044     DEVICE = MPIRANK % GPUS;                                    // Get GPU device ID from MPI rank
00045   }
00046 
00047 //! Destructor
00048   ~MyMPI() {
00049     int ExternalMPI;                                            // Flag for external MPI call
00050     MPI_Initialized(&ExternalMPI);                              // Check if MPI_Init has been called
00051     if(!ExternalMPI) MPI_Finalize();                            // Finalize MPI communicator
00052   }
00053 
00054 //! If n is power of two return true
00055   bool isPowerOfTwo(const int n) {
00056     return ((n != 0) && !(n & (n - 1)));                        // Decrement and compare bits
00057   }
00058 
00059 //! Split range and return partial range
00060   void splitRange(int &begin, int &end, int iSplit, int numSplit) {
00061     int size = end - begin;                                     // Size of range
00062     int increment = size / numSplit;                            // Increment of splitting
00063     int remainder = size % numSplit;                            // Remainder of splitting
00064     begin += iSplit * increment + std::min(iSplit,remainder);   // Increment the begin counter
00065     end = begin + increment;                                    // Increment the end counter
00066     if( remainder > iSplit ) end++;                             // Adjust the end counter for remainder
00067   }
00068 
00069 //! Get MPI data type
00070   template<typename T>
00071   MPI_Datatype getType(T object) {
00072     MPI_Datatype type = MPI_BYTE;                               // MPI data type
00073     if       ( typeid(object) == typeid(char) ) {               // If data type is char
00074       type = MPI_CHAR;                                          //  use MPI_CHAR
00075     } else if( typeid(object) == typeid(short) ) {              // If data type is short
00076       type = MPI_SHORT;                                         //  use MPI_SHORT
00077     } else if( typeid(object) == typeid(int) ) {                // If data type is int
00078       type = MPI_INT;                                           //  use MPI_INT
00079     } else if( typeid(object) == typeid(long) ) {               // If data type is long
00080       type = MPI_LONG;                                          //  use MPI_LONG
00081     } else if( typeid(object) == typeid(long long) ) {          // If data type is long long
00082       type = MPI_LONG_LONG;                                     //  use MPI_LONG_LONG
00083     } else if( typeid(object) == typeid(unsigned char) ) {      // If data type is unsigned char
00084       type = MPI_UNSIGNED_CHAR;                                 //  use MPI_UNSIGNED_CHAR
00085     } else if( typeid(object) == typeid(unsigned short) ) {     // If data type is unsigned short
00086       type = MPI_UNSIGNED_SHORT;                                //  use MPI_UNSIGNED_SHORT
00087     } else if( typeid(object) == typeid(unsigned int) ) {       // If data type is unsigned int
00088       type = MPI_UNSIGNED;                                      //  use MPI_UNSIGNED
00089     } else if( typeid(object) == typeid(unsigned long) ) {      // If data type is unsigned long
00090       type = MPI_UNSIGNED_LONG;                                 //  use MPI_UNSIGNED_LONG
00091     } else if( typeid(object) == typeid(unsigned long long) ) { // If data type is unsigned long long
00092       type = MPI_UNSIGNED_LONG_LONG;                            //  use MPI_UNSIGNED_LONG_LONG
00093     } else if( typeid(object) == typeid(float) ) {              // If data type is float
00094       type = MPI_FLOAT;                                         //  use MPI_FLOAT
00095     } else if( typeid(object) == typeid(double) ) {             // If data type is double
00096       type = MPI_DOUBLE;                                        //  use MPI_DOUBLE
00097     } else if( typeid(object) == typeid(long double) ) {        // If data type is long double
00098       type = MPI_LONG_DOUBLE;                                   //  use MPI_LONG_DOUBLE
00099     } else if( typeid(object) == typeid(std::complex<float>) ) {// If data type is complex<float>
00100       type = MPI_COMPLEX;                                       //  use MPI_COMPLEX
00101     } else if( typeid(object) == typeid(std::complex<double>) ) {// If data type is compelx<double>
00102       type = MPI_DOUBLE_COMPLEX;                                //  use MPI_DOUBLE_COMPLEX
00103     }                                                           // Endif for data type
00104     return type;                                                // Return MPI data type
00105   }
00106 
00107 //! Print a scalar value on all ranks
00108   template<typename T>
00109   void print(T data) {
00110     for( int irank=0; irank!=MPISIZE; ++irank ) {               // Loop over ranks
00111       MPI_Barrier(MPI_COMM_WORLD);                              //  Sync processes
00112       usleep(WAIT);                                             //  Wait "WAIT" milliseconds
00113       if( MPIRANK == irank ) std::cout << data << " ";          //  If it's my turn print "data"
00114     }                                                           // End loop over ranks
00115     MPI_Barrier(MPI_COMM_WORLD);                                // Sync processes
00116     usleep(WAIT);                                               // Wait "WAIT" milliseconds
00117     if( MPIRANK == 0 ) std::cout << std::endl;                  // New line
00118   }
00119 
00120 //! Print a scalar value on irank
00121   template<typename T>
00122   void print(T data, const int irank) {
00123     MPI_Barrier(MPI_COMM_WORLD);                                // Sync processes
00124     usleep(WAIT);                                               // Wait "WAIT" milliseconds
00125     if( MPIRANK == irank ) std::cout << data;                   // If it's my rank print "data"
00126   }
00127 
00128 //! Print a vector value on all ranks
00129   template<typename T>
00130   void print(T *data, const int begin, const int end) {
00131     for( int irank=0; irank!=MPISIZE; ++irank ) {               // Loop over ranks
00132       MPI_Barrier(MPI_COMM_WORLD);                              //  Sync processes
00133       usleep(WAIT);                                             //  Wait "WAIT" milliseconds
00134       if( MPIRANK == irank ) {                                  //  If it's my turn to print
00135         std::cout << MPIRANK << " : ";                          //   Print rank
00136         for( int i=begin; i!=end; ++i ) {                       //   Loop over data
00137           std::cout << data[i] << " ";                          //    Print data[i]
00138         }                                                       //   End loop over data
00139         std::cout << std::endl;                                 //   New line
00140       }                                                         //  Endif for my turn
00141     }                                                           // End loop over ranks
00142   }
00143 
00144 //! Print a vector value on irank
00145   template<typename T>
00146   void print(T *data, const int begin, const int end, const int irank) {
00147     MPI_Barrier(MPI_COMM_WORLD);                                // Sync processes
00148     usleep(WAIT);                                               // Wait "WAIT" milliseconds
00149     if( MPIRANK == irank ) {                                    // If it's my rank
00150       std::cout << MPIRANK << " : ";                            //  Print rank
00151       for( int i=begin; i!=end; ++i ) {                         //  Loop over data
00152         std::cout << data[i] << " ";                            //   Print data[i]
00153       }                                                         //  End loop over data
00154       std::cout << std::endl;                                   //  New line
00155     }                                                           // Endif for my rank
00156   }
00157 };
00158 
00159 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines