ExaFMM 1
Fast-multipole Method for exascale systems
|
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