1 /*************************************************************************** 2 * Copyright (C) 2015 by * 3 * Lam-Tung Nguyen <nltung@gmail.com> * 4 * * 5 * * 6 * This program is free software; you can redistribute it and/or modify * 7 * it under the terms of the GNU General Public License as published by * 8 * the Free Software Foundation; either version 2 of the License, or * 9 * (at your option) any later version. * 10 * * 11 * This program is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 * GNU General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU General Public License * 17 * along with this program; if not, write to the * 18 * Free Software Foundation, Inc., * 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 20 ***************************************************************************/ 21 22 #ifndef MPIHELPER_H 23 #define MPIHELPER_H 24 25 #include <string> 26 #include <vector> 27 #include "utils/tools.h" 28 #include "utils/checkpoint.h" 29 30 #ifdef _IQTREE_MPI 31 #include <mpi.h> 32 #endif 33 34 #define PROC_MASTER 0 35 #define TREE_TAG 1 // Message contain trees 36 #define STOP_TAG 2 // Stop message 37 #define BOOT_TAG 3 // Message to please send bootstrap trees 38 #define BOOT_TREE_TAG 4 // bootstrap tree tag 39 #define LOGL_CUTOFF_TAG 5 // send logl_cutoff for ultrafast bootstrap 40 41 using namespace std; 42 43 class MPIHelper { 44 public: 45 /** 46 * Singleton method: get one and only one getInstance of the class 47 */ 48 static MPIHelper &getInstance(); 49 50 /** initialize MPI */ 51 void init(int argc, char *argv[]); 52 53 /** finalize MPI */ 54 void finalize(); 55 56 /** 57 destructor 58 */ 59 ~MPIHelper(); 60 getNumProcesses()61 int getNumProcesses() const { 62 return numProcesses; 63 } 64 setNumProcesses(int numProcesses)65 void setNumProcesses(int numProcesses) { 66 MPIHelper::numProcesses = numProcesses; 67 } 68 getProcessID()69 int getProcessID() const { 70 return processID; 71 } 72 isMaster()73 bool isMaster() const { 74 return processID == PROC_MASTER; 75 } 76 isWorker()77 bool isWorker() const { 78 return processID != PROC_MASTER; 79 } 80 setProcessID(int processID)81 void setProcessID(int processID) { 82 MPIHelper::processID = processID; 83 } 84 85 /** synchronize random seed from master to all workers */ 86 void syncRandomSeed(); 87 88 /** count the number of host with the same name as the current host */ 89 int countSameHost(); 90 91 /** @return true if got any message from another process */ 92 bool gotMessage(); 93 94 95 /** wrapper for MPI_Send a string 96 @param str string to send 97 @param dest destination process 98 @param tag message tag 99 */ 100 101 #ifdef _IQTREE_MPI 102 void sendString(string &str, int dest, int tag); 103 104 /** wrapper for MPI_Recv a string 105 @param[out] str string received 106 @param src source process 107 @param tag message tag 108 @return the source process that sent the message 109 */ 110 int recvString(string &str, int src = MPI_ANY_SOURCE, int tag = MPI_ANY_TAG); 111 112 /** wrapper for MPI_Send an entire Checkpoint object 113 @param ckp Checkpoint object to send 114 @param dest destination process 115 */ 116 void sendCheckpoint(Checkpoint *ckp, int dest); 117 118 /** wrapper for MPI_Recv an entire Checkpoint object 119 @param[out] ckp Checkpoint object received 120 @param src source process 121 @param tag message tag 122 @return the source process that sent the message 123 */ 124 int recvCheckpoint(Checkpoint *ckp, int src = MPI_ANY_SOURCE); 125 126 /** 127 wrapper for MPI_Bcast to broadcast checkpoint from Master to all Workers 128 @param ckp Checkpoint object 129 */ 130 void broadcastCheckpoint(Checkpoint *ckp); 131 132 /** 133 wrapper for MPI_Gather to gather all checkpoints into Master 134 @param ckp Checkpoint object 135 */ 136 void gatherCheckpoint(Checkpoint *ckp); 137 #endif 138 139 void increaseTreeSent(int inc = 1) { 140 numTreeSent += inc; 141 } 142 143 void increaseTreeReceived(int inc = 1) { 144 numTreeReceived += inc; 145 } 146 147 private: 148 /** 149 * Remove the buffers for finished messages 150 */ 151 int cleanUpMessages(); 152 153 private: MPIHelper()154 MPIHelper() { }; // Disable constructor MPIHelper(MPIHelper const &)155 MPIHelper(MPIHelper const &) { }; // Disable copy constructor 156 void operator=(MPIHelper const &) { }; // Disable assignment 157 158 int processID; 159 160 int numProcesses; 161 162 public: getNumTreeReceived()163 int getNumTreeReceived() const { 164 return numTreeReceived; 165 } 166 setNumTreeReceived(int numTreeReceived)167 void setNumTreeReceived(int numTreeReceived) { 168 MPIHelper::numTreeReceived = numTreeReceived; 169 } 170 getNumTreeSent()171 int getNumTreeSent() const { 172 return numTreeSent; 173 } 174 setNumTreeSent(int numTreeSent)175 void setNumTreeSent(int numTreeSent) { 176 MPIHelper::numTreeSent = numTreeSent; 177 } 178 resetNumbers()179 void resetNumbers() { 180 // numTreeSent = 0; 181 // numTreeReceived = 0; 182 // numNNISearch = 0; 183 } 184 185 private: 186 int numTreeSent; 187 188 int numTreeReceived; 189 190 public: getNumNNISearch()191 int getNumNNISearch() const { 192 return numNNISearch; 193 } 194 setNumNNISearch(int numNNISearch)195 void setNumNNISearch(int numNNISearch) { 196 MPIHelper::numNNISearch = numNNISearch; 197 } 198 199 private: 200 int numNNISearch; 201 202 203 }; 204 205 #endif 206