00001 // @(#)root/minuit2:$Id: MPIProcess.h 29227 2009-06-25 15:22:12Z brun $ 00002 // Author: A. Lazzaro 2009 00003 /*************************************************************************** 00004 * Package: Minuit2 * 00005 * File: $Id: MPIProcess.h 29227 2009-06-25 15:22:12Z brun $ * 00006 * Author: Alfio Lazzaro, alfio.lazzaro@mi.infn.it * 00007 * * 00008 * Copyright: (C) 2008 by Universita' and INFN, Milan * 00009 ***************************************************************************/ 00010 00011 #ifndef ROOT_Minuit2_MPIProcess 00012 #define ROOT_Minuit2_MPIProcess 00013 00014 // disable MPI calls 00015 //#define MPIPROC 00016 00017 #include "Minuit2/MnMatrix.h" 00018 00019 #ifdef MPIPROC 00020 #include "mpi.h" 00021 #endif 00022 00023 00024 namespace ROOT { 00025 00026 namespace Minuit2 { 00027 00028 class MPITerminate { 00029 public: 00030 ~MPITerminate() { 00031 #ifdef MPIPROC 00032 if (MPI::Is_initialized() && !(MPI::Is_finalized())) { 00033 std::cout << "Info --> MPITerminate:: End MPI on #" 00034 << MPI::COMM_WORLD.Get_rank() << " processor" 00035 << std::endl; 00036 00037 MPI::Finalize(); 00038 } 00039 #endif 00040 } 00041 00042 }; 00043 00044 00045 class MPIProcess { 00046 public: 00047 MPIProcess(unsigned int nelements, unsigned int indexComm); 00048 ~MPIProcess(); 00049 00050 inline unsigned int NumElements4JobIn() const { return fNumElements4JobIn; } 00051 inline unsigned int NumElements4JobOut() const { return fNumElements4JobOut; } 00052 00053 inline unsigned int NumElements4Job(unsigned int rank) const 00054 { return NumElements4JobIn()+((rank<NumElements4JobOut()) ? 1 : 0); } 00055 00056 inline unsigned int StartElementIndex() const 00057 { return ((fRank<NumElements4JobOut()) ? (fRank*NumElements4Job(fRank)) : 00058 (fNelements-(fSize-fRank)*NumElements4Job(fRank))); } 00059 00060 inline unsigned int EndElementIndex() const 00061 { return StartElementIndex()+NumElements4Job(fRank); } 00062 00063 inline unsigned int GetMPISize() const { return fSize; } 00064 inline unsigned int GetMPIRank() const { return fRank; } 00065 00066 bool SyncVector(ROOT::Minuit2::MnAlgebraicVector &mnvector); 00067 bool SyncSymMatrixOffDiagonal(ROOT::Minuit2::MnAlgebraicSymMatrix &mnmatrix); 00068 00069 static unsigned int GetMPIGlobalRank() { StartMPI(); return fgGlobalRank; } 00070 static unsigned int GetMPIGlobalSize() { StartMPI(); return fgGlobalSize; } 00071 static inline void StartMPI() { 00072 #ifdef MPIPROC 00073 if (!(MPI::Is_initialized())) { 00074 MPI::Init(); 00075 std::cout << "Info --> MPIProcess::StartMPI: Start MPI on #" 00076 << MPI::COMM_WORLD.Get_rank() << " processor" 00077 << std::endl; 00078 } 00079 fgGlobalSize = MPI::COMM_WORLD.Get_size(); 00080 fgGlobalRank = MPI::COMM_WORLD.Get_rank(); 00081 #endif 00082 } 00083 00084 static void TerminateMPI() { 00085 #ifdef MPIPROC 00086 if (fgCommunicators[0]!=0 && fgCommunicators[1]!=0) { 00087 delete fgCommunicators[0]; fgCommunicators[0] = 0; fgIndecesComm[0] = 0; 00088 delete fgCommunicators[1]; fgCommunicators[1] = 0; fgIndecesComm[1] = 0; 00089 } 00090 00091 MPITerminate(); 00092 00093 #endif 00094 } 00095 00096 static bool SetCartDimension(unsigned int dimX, unsigned int dimY); 00097 static bool SetDoFirstMPICall(bool doFirstMPICall = true); 00098 00099 inline void SumReduce(const double& sub, double& total) { 00100 total = sub; 00101 00102 #ifdef MPIPROC 00103 if (fSize>1) { 00104 fgCommunicator->Allreduce(&sub,&total,1,MPI::DOUBLE,MPI::SUM); 00105 } 00106 #endif 00107 } 00108 00109 private: 00110 00111 #ifdef MPIPROC 00112 void MPISyncVector(double *ivector, int svector, double *ovector); 00113 #endif 00114 00115 private: 00116 unsigned int fNelements; 00117 unsigned int fSize; 00118 unsigned int fRank; 00119 00120 static unsigned int fgGlobalSize; 00121 static unsigned int fgGlobalRank; 00122 00123 static unsigned int fgCartSizeX; 00124 static unsigned int fgCartSizeY; 00125 static unsigned int fgCartDimension; 00126 static bool fgNewCart; 00127 00128 unsigned int fNumElements4JobIn; 00129 unsigned int fNumElements4JobOut; 00130 00131 #ifdef MPIPROC 00132 static MPI::Intracomm *fgCommunicator; 00133 static int fgIndexComm; // maximum 2 communicators, so index can be 0 and 1 00134 static MPI::Intracomm *fgCommunicators[2]; // maximum 2 communicators 00135 static unsigned int fgIndecesComm[2]; 00136 #endif 00137 00138 }; 00139 00140 } // namespace Minuit2 00141 } // namespace ROOT 00142 00143 #endif 00144 00145