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