- Home
- About DUNE
- Download
- Documentation
- Community
- Development
00001 // vi: set et ts=4 sw=2 sts=2: 00002 #ifndef DUNE_MPICOLLECTIVECOMMUNICATION_HH 00003 #define DUNE_MPICOLLECTIVECOMMUNICATION_HH 00004 00010 #include<iostream> 00011 #include<complex> 00012 #include<algorithm> 00013 #include<functional> 00014 00015 #include "deprecated.hh" 00016 #include"exceptions.hh" 00017 #include"collectivecommunication.hh" 00018 #include"binaryfunctions.hh" 00019 #include"shared_ptr.hh" 00020 #include"mpitraits.hh" 00021 00022 #if HAVE_MPI 00023 // MPI header 00024 #include<mpi.h> 00025 00026 namespace Dune 00027 { 00028 00029 //======================================================= 00030 // use singleton pattern and template specialization to 00031 // generate MPI data types 00032 //======================================================= 00033 00034 // any type is interpreted as contiguous piece of memory 00035 // i.e. only value types are allowed ! 00036 template<typename T> 00037 class Generic_MPI_Datatype 00038 { 00039 public: 00040 static MPI_Datatype get() DUNE_DEPRECATED 00041 { 00042 if (!type) 00043 { 00044 type = shared_ptr<MPI_Datatype>(new MPI_Datatype); 00045 MPI_Type_contiguous(sizeof(T),MPI_BYTE,type.get()); 00046 MPI_Type_commit(type.get()); 00047 } 00048 return *type; 00049 } 00050 private: 00051 Generic_MPI_Datatype () {} 00052 Generic_MPI_Datatype (const Generic_MPI_Datatype& ) {} 00053 static shared_ptr<MPI_Datatype> type; 00054 }; 00055 00056 template<typename T> 00057 shared_ptr<MPI_Datatype> Generic_MPI_Datatype<T>::type = shared_ptr<MPI_Datatype>(static_cast<MPI_Datatype*>(0)); 00058 00059 // A Macro for defining traits for the primitive data types 00060 #define ComposeMPITraits(p,m) \ 00061 template<> \ 00062 class Generic_MPI_Datatype<p>{ \ 00063 public: \ 00064 static inline MPI_Datatype get() DUNE_DEPRECATED{ \ 00065 return m; \ 00066 } \ 00067 } 00068 00069 00070 ComposeMPITraits(char, MPI_CHAR); 00071 ComposeMPITraits(unsigned char,MPI_UNSIGNED_CHAR); 00072 ComposeMPITraits(short,MPI_SHORT); 00073 ComposeMPITraits(unsigned short,MPI_UNSIGNED_SHORT); 00074 ComposeMPITraits(int,MPI_INT); 00075 ComposeMPITraits(unsigned int,MPI_UNSIGNED); 00076 ComposeMPITraits(long,MPI_LONG); 00077 ComposeMPITraits(unsigned long,MPI_UNSIGNED_LONG); 00078 ComposeMPITraits(float,MPI_FLOAT); 00079 ComposeMPITraits(double,MPI_DOUBLE); 00080 ComposeMPITraits(long double,MPI_LONG_DOUBLE); 00081 00082 #undef ComposeMPITraits 00083 00084 //======================================================= 00085 // use singleton pattern and template specialization to 00086 // generate MPI operations 00087 //======================================================= 00088 00089 template<typename Type, typename BinaryFunction> 00090 class Generic_MPI_Op 00091 { 00092 00093 public: 00094 static MPI_Op get () 00095 { 00096 if (!op) 00097 { 00098 op = shared_ptr<MPI_Op>(new MPI_Op); 00099 MPI_Op_create((void (*)(void*, void*, int*, MPI_Datatype*))&operation,true,op.get()); 00100 } 00101 return *op; 00102 } 00103 private: 00104 static void operation (Type *in, Type *inout, int *len, MPI_Datatype *dptr) 00105 { 00106 BinaryFunction func; 00107 00108 for (int i=0; i< *len; ++i, ++in, ++inout){ 00109 Type temp; 00110 temp = func(*in, *inout); 00111 *inout = temp; 00112 } 00113 } 00114 Generic_MPI_Op () {} 00115 Generic_MPI_Op (const Generic_MPI_Op& ) {} 00116 static shared_ptr<MPI_Op> op; 00117 }; 00118 00119 00120 template<typename Type, typename BinaryFunction> 00121 shared_ptr<MPI_Op> Generic_MPI_Op<Type,BinaryFunction>::op = shared_ptr<MPI_Op>(static_cast<MPI_Op*>(0)); 00122 00123 #define ComposeMPIOp(type,func,op) \ 00124 template<> \ 00125 class Generic_MPI_Op<type, func<type> >{ \ 00126 public:\ 00127 static MPI_Op get(){ \ 00128 return op; \ 00129 } \ 00130 private:\ 00131 Generic_MPI_Op () {}\ 00132 Generic_MPI_Op (const Generic_MPI_Op& ) {}\ 00133 } 00134 00135 00136 ComposeMPIOp(char, std::plus, MPI_SUM); 00137 ComposeMPIOp(unsigned char, std::plus, MPI_SUM); 00138 ComposeMPIOp(short, std::plus, MPI_SUM); 00139 ComposeMPIOp(unsigned short, std::plus, MPI_SUM); 00140 ComposeMPIOp(int, std::plus, MPI_SUM); 00141 ComposeMPIOp(unsigned int, std::plus, MPI_SUM); 00142 ComposeMPIOp(long, std::plus, MPI_SUM); 00143 ComposeMPIOp(unsigned long, std::plus, MPI_SUM); 00144 ComposeMPIOp(float, std::plus, MPI_SUM); 00145 ComposeMPIOp(double, std::plus, MPI_SUM); 00146 ComposeMPIOp(long double, std::plus, MPI_SUM); 00147 00148 ComposeMPIOp(char, std::multiplies, MPI_PROD); 00149 ComposeMPIOp(unsigned char, std::multiplies, MPI_PROD); 00150 ComposeMPIOp(short, std::multiplies, MPI_PROD); 00151 ComposeMPIOp(unsigned short, std::multiplies, MPI_PROD); 00152 ComposeMPIOp(int, std::multiplies, MPI_PROD); 00153 ComposeMPIOp(unsigned int, std::multiplies, MPI_PROD); 00154 ComposeMPIOp(long, std::multiplies, MPI_PROD); 00155 ComposeMPIOp(unsigned long, std::multiplies, MPI_PROD); 00156 ComposeMPIOp(float, std::multiplies, MPI_PROD); 00157 ComposeMPIOp(double, std::multiplies, MPI_PROD); 00158 ComposeMPIOp(long double, std::multiplies, MPI_PROD); 00159 00160 ComposeMPIOp(char, Min, MPI_MIN); 00161 ComposeMPIOp(unsigned char, Min, MPI_MIN); 00162 ComposeMPIOp(short, Min, MPI_MIN); 00163 ComposeMPIOp(unsigned short, Min, MPI_MIN); 00164 ComposeMPIOp(int, Min, MPI_MIN); 00165 ComposeMPIOp(unsigned int, Min, MPI_MIN); 00166 ComposeMPIOp(long, Min, MPI_MIN); 00167 ComposeMPIOp(unsigned long, Min, MPI_MIN); 00168 ComposeMPIOp(float, Min, MPI_MIN); 00169 ComposeMPIOp(double, Min, MPI_MIN); 00170 ComposeMPIOp(long double, Min, MPI_MIN); 00171 00172 ComposeMPIOp(char, Max, MPI_MAX); 00173 ComposeMPIOp(unsigned char, Max, MPI_MAX); 00174 ComposeMPIOp(short, Max, MPI_MAX); 00175 ComposeMPIOp(unsigned short, Max, MPI_MAX); 00176 ComposeMPIOp(int, Max, MPI_MAX); 00177 ComposeMPIOp(unsigned int, Max, MPI_MAX); 00178 ComposeMPIOp(long, Max, MPI_MAX); 00179 ComposeMPIOp(unsigned long, Max, MPI_MAX); 00180 ComposeMPIOp(float, Max, MPI_MAX); 00181 ComposeMPIOp(double, Max, MPI_MAX); 00182 ComposeMPIOp(long double, Max, MPI_MAX); 00183 00184 #undef ComposeMPIOp 00185 00186 00187 //======================================================= 00188 // use singleton pattern and template specialization to 00189 // generate MPI operations 00190 //======================================================= 00191 00195 template<> 00196 class CollectiveCommunication<MPI_Comm> 00197 { 00198 public: 00200 CollectiveCommunication (const MPI_Comm& c) 00201 : communicator(c) 00202 { 00203 if(communicator!=MPI_COMM_NULL){ 00204 MPI_Comm_rank(communicator,&me); 00205 MPI_Comm_size(communicator,&procs); 00206 }else{ 00207 procs=0; 00208 me=-1; 00209 } 00210 } 00211 00213 int rank () const 00214 { 00215 return me; 00216 } 00217 00219 int size () const 00220 { 00221 return procs; 00222 } 00223 00225 template<typename T> 00226 T sum (T& in) const // MPI does not know about const :-( 00227 { 00228 T out; 00229 allreduce<std::plus<T> >(&in,&out,1); 00230 return out; 00231 } 00232 00234 template<typename T> 00235 int sum (T* inout, int len) const 00236 { 00237 return allreduce<std::plus<T> >(inout,len); 00238 } 00239 00241 template<typename T> 00242 T prod (T& in) const // MPI does not know about const :-( 00243 { 00244 T out; 00245 allreduce<std::multiplies<T> >(&in,&out,1); 00246 return out; 00247 } 00248 00250 template<typename T> 00251 int prod (T* inout, int len) const 00252 { 00253 return allreduce<std::plus<T> >(inout,len); 00254 } 00255 00257 template<typename T> 00258 T min (T& in) const // MPI does not know about const :-( 00259 { 00260 T out; 00261 allreduce<Min<T> >(&in,&out,1); 00262 return out; 00263 } 00264 00266 template<typename T> 00267 int min (T* inout, int len) const 00268 { 00269 return allreduce<Min<T> >(inout,len); 00270 } 00271 00272 00274 template<typename T> 00275 T max (T& in) const // MPI does not know about const :-( 00276 { 00277 T out; 00278 allreduce<Max<T> >(&in,&out,1); 00279 return out; 00280 } 00281 00283 template<typename T> 00284 int max (T* inout, int len) const 00285 { 00286 return allreduce<Max<T> >(inout,len); 00287 } 00288 00290 int barrier () const 00291 { 00292 return MPI_Barrier(communicator); 00293 } 00294 00296 template<typename T> 00297 int broadcast (T* inout, int len, int root) const 00298 { 00299 return MPI_Bcast(inout,len,MPITraits<T>::getType(),root,communicator); 00300 } 00301 00303 template<typename T> 00304 int gather (T* in, T* out, int len, int root) const // note out must have space for P*len elements 00305 { 00306 return MPI_Gather(in,len,MPITraits<T>::getType(), 00307 out,len,MPITraits<T>::getType(), 00308 root,communicator); 00309 } 00310 00311 operator MPI_Comm () const 00312 { 00313 return communicator; 00314 } 00315 00316 template<typename BinaryFunction, typename Type> 00317 int allreduce(Type* inout, int len) const 00318 { 00319 Type* out = new Type[len]; 00320 int ret = allreduce<BinaryFunction>(inout,out,len); 00321 std::copy(out, out+len, inout); 00322 delete[] out; 00323 return ret; 00324 } 00325 00326 template<typename BinaryFunction, typename Type> 00327 int allreduce(Type* in, Type* out, int len) const 00328 { 00329 return MPI_Allreduce(in, out, len, MPITraits<Type>::getType(), 00330 Generic_MPI_Op<Type, BinaryFunction>::get(),communicator); 00331 } 00332 00333 private: 00334 MPI_Comm communicator; 00335 int me; 00336 int procs; 00337 }; 00338 } // namespace dune 00339 00340 #endif 00341 #endif
Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].