Chombo + EB  3.0
SPMDI.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 #ifndef _SPMDI_H_
12 #define _SPMDI_H_
13 
14 #include "memtrack.H"
15 #include "BaseNamespaceHeader.H"
16 
17 // default implementations for linearization routines.
18 
19 template <class T>
20 int linearSize(const T& inputT)
21 {
22  return inputT.linearSize();
23 }
24 
25 template <class T>
26 void linearIn(T& a_outputT, const void* const inBuf)
27 {
28  a_outputT.linearIn(inBuf);
29 }
30 
31 template <class T>
32 void linearOut(void* const a_outBuf, const T& inputT)
33 {
34  inputT.linearOut(a_outBuf);
35 }
36 
37 #ifdef CH_MPI
38 
39 extern void AttachDebugger(int);
40 /*****************************/
41 //gather a_input into a a_outVec
42 /*****************************/
43 template <class T>
44 inline void
45 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
46 {
47  CH_assert (a_dest >= 0);
48  CH_assert(a_dest < numProc());
49  //now THIS size lives on THIS processor
50  int isize = linearSize(a_input);
51 
52  //make stuff for linearout
53  void* loclBuf = mallocMT(isize);
54  if (loclBuf == NULL)
55  MayDay::Error("out of memory in gather 1");
56 
57  //put linearized T into its proper buffer
58  linearOut(loclBuf, a_input);
59 
60  int nProcess = numProc();
61  int sendCount = 1;
62  int recdCount = 1;
63 
64  //need to gather isizes onto processor a_dest
65  int* vectSize = NULL;
66  int* vectDisp = NULL;
67  void* sendBuf = static_cast<void*>(&isize);
68  //allocate received buffer
69  if (procID() == a_dest)
70  {
71  vectSize = new int[nProcess];
72  vectDisp = new int[nProcess];
73  }
74 
75  int result1 = MPI_Gather(sendBuf, sendCount, MPI_INT,
76  vectSize,recdCount, MPI_INT,
77  a_dest, Chombo_MPI::comm);
78 
79  if (result1 != MPI_SUCCESS)
80  MayDay::Error("Gather<T> failed in MPI_Gather 1");
81 
82  //make memory for gather, linearin
83  void* recdBuf = NULL;
84  if (procID() == a_dest)
85  {
86  int itotsize=0;
87  for (int iproc = 0; iproc < nProcess; iproc++)
88  {
89  vectDisp[iproc] = itotsize;
90  itotsize += vectSize[iproc];
91  }
92  recdBuf = mallocMT(itotsize);
93  if (recdBuf == NULL)
94  MayDay::Error("out of memory in gather 2");
95  }
96 
97  //gather data
98  int result2 = MPI_Gatherv(loclBuf, isize, MPI_BYTE,
99  recdBuf, vectSize, vectDisp, MPI_BYTE,
100  a_dest, Chombo_MPI::comm);
101  if (result2 != MPI_SUCCESS)
102  MayDay::Error("Gather<T> failed in MPI_Gather 2");
103 
104  if (procID() == a_dest)
105  {
106  //calculate offset into array for current processor
107  int ioffset = 0;
108  a_outVec.resize(nProcess);
109  //need to cast to char* to do pointer arithmetic
110  char* arithPtr = (char*)recdBuf;
111  for (int iproc = 0; iproc < nProcess; iproc++)
112  {
113  ioffset = vectDisp[iproc];
114  char* thisProcBuf = arithPtr + ioffset;
115  linearIn(a_outVec[iproc], thisProcBuf);
116  }
117 
118  //delete memory for dest-specific arrays
119  delete[] vectSize;
120  delete[] vectDisp;
121  freeMT(recdBuf);
122  }
123 
124  //delete memory for local buffer
125  freeMT(loclBuf);
126 }
127 
128 /*****************************/
129 //broadcast T everywhere
130 /*****************************/
131 template <class T>
132 inline void
133 broadcast(T& a_inAndOut, int a_src)
134 {
135  CH_assert (a_src >= 0);
136  CH_assert(a_src < numProc());
137  int isize;
138  if (procID() == a_src)
139  {
140  isize = linearSize(a_inAndOut);
141  }
142 
143  MPI_Bcast(&isize, 1, MPI_INT, a_src, Chombo_MPI::comm);
144 
145  void* broadBuf = mallocMT(isize);
146 
147  if (broadBuf == NULL)
148  {
149  MayDay::Error("out of memory in broadcast");
150  }
151 
152  //take inAndOut from src and put it into broadBuf
153  if (procID() == a_src)
154  {
155  linearOut(broadBuf, a_inAndOut);
156  }
157 
158  //broadcast broadBuf to all procs
159  MPI_Bcast(broadBuf, isize, MPI_BYTE, a_src, Chombo_MPI::comm);
160 
161  if (procID()==a_src)
162  {
163  CH_MaxMPISendSize = Max<long long>(CH_MaxMPISendSize, isize);
164  }
165  else
166  {
167  CH_MaxMPIRecvSize = Max<long long>(CH_MaxMPIRecvSize, isize);
168  }
169  //take broadBuf and put back into inAndOut if not src
170  if (procID() != a_src)
171  {
172  linearIn(a_inAndOut, broadBuf);
173  }
174 
175  //delete memory for buffer
176  freeMT(broadBuf);
177 }
178 
179 /*****************************/
180 // simple Barrier
181 /*****************************/
182 inline void
183 barrier(void)
184 {
185  MPI_Barrier(Chombo_MPI::comm);
186 }
187 
188 #else
189 /*****************************/
190 //non-mpi version
191 /*****************************/
192 template <class T>
193 inline void
194 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
195 {
196  a_outVec.resize(1);
197  a_outVec[0] = a_input;
198 }
199 /*****************************/
200 //non-mpi version
201 /*****************************/
202 template <class T>
203 inline void
204 broadcast(T& a_inAndOut, int a_src)
205 {
206  //nothing to do. in and out are the same with one proc
207 }
208 /*****************************/
209 //non-mpi version
210 /*****************************/
211 inline void
212 barrier(void)
213 {
214  // do nothing in serial
215 }
216 
217 #endif //the mpi thing
218 
219 //*************************************
220 //These should work independent of MPI
221 //*************************************
222 
223 //Vector<T> specialization of linearIn
224 template <class T>
225 void
226 linearListIn(Vector<T>& a_outputT, const void* const a_inBuf)
227 {
228  //first entry is the size of the vector
229  const int* const intBuf = (int*)a_inBuf;
230  int vecsize = intBuf[0];
231  Vector<int> vecOffset(vecsize);
232  //next vecsize entries are offsets of data into buffer
233  for (int ivec = 0; ivec < vecsize; ivec++)
234  {
235  vecOffset[ivec] = intBuf[ivec+1];
236  }
237  //next vecsize entries are the actual data
238  //yes I could do this in one loop but that would
239  // either
240  // a) make it less symmetric with linearOut
241  // and/or
242  // b) make both of them far less readable
243  a_outputT.resize(vecsize);
244  const char* const charbuf = (char*)a_inBuf;
245  for (int ivec = 0; ivec < vecsize; ivec++)
246  {
247  const char* const dataLoc = charbuf + vecOffset[ivec];
248  linearIn(a_outputT[ivec], dataLoc);
249  }
250 }
251 
252 //Vector<T> specialization of linearOut
253 template <class T>
254 void
255 linearListOut(void* const a_outBuf, const Vector<T>& a_input)
256 {
257  //first entry is the size of the vector
258  int* const intBuf = (int*)a_outBuf;
259  intBuf[0] = a_input.size();
260  int vecsize = intBuf[0];
261  Vector<int> vecOffset(vecsize);
262  //next vecsize entries are offsets of data into buffer
263  //next vecsize entries are the actual data
264  int ioffset = (vecsize+1)*sizeof(int);
265  for (int ivec = 0; ivec < vecsize; ivec++)
266  {
267  intBuf[ivec+1] = ioffset;
268  vecOffset[ivec] = ioffset;
269  ioffset += linearSize(a_input[ivec]);
270  }
271  //yes I could do this in one loop but that would
272  // either
273  // a) make it less symmetric with linearIn
274  // and/or
275  // b) make both of them far less readable
276  char* const charBuf = (char*)a_outBuf;
277  for (int ivec = 0; ivec < vecsize; ivec++)
278  {
279  char* const dataLoc = charBuf + vecOffset[ivec];
280  linearOut(dataLoc, a_input[ivec]);
281  }
282 }
283 
284 //Vector<T> specialization of linearSize
285 template <class T>
286 int
287 linearListSize(const Vector<T>& a_input)
288 {
289  //first entry is the size of the vector (int)
290  //next vecsize entries are offsets of data into buffer (int)
291  //next vecsize entries are the actual data
292  int itotsize = (a_input.size() + 1)*sizeof(int);
293  for (int ivec = 0; ivec < a_input.size(); ivec++)
294  {
295  itotsize += linearSize(a_input[ivec]);
296  }
297  return itotsize;
298 }
299 
300 #include "BaseNamespaceFooter.H"
301 
302 #endif
#define freeMT(a_a)
Definition: memtrack.H:159
#define CH_assert(cond)
Definition: CHArray.H:37
void linearOut(void *const a_outBuf, const T &inputT)
Definition: SPMDI.H:32
void barrier(void)
all ranks wait here to sync-up
Definition: SPMDI.H:212
one dimensional dynamic array
Definition: Vector.H:52
long long CH_MaxMPISendSize
#define mallocMT(a_a)
Definition: memtrack.H:158
long long CH_MaxMPIRecvSize
void AttachDebugger(int a_sig=4)
void linearIn(T &a_outputT, const void *const inBuf)
Definition: SPMDI.H:26
unsigned int numProc()
number of parallel processes
int linearSize(const T &inputT)
Definition: SPMDI.H:20
void resize(unsigned int isize)
Definition: Vector.H:323
void gather(Vector< T > &a_outVec, const T &a_input, int a_dest)
Definition: SPMDI.H:194
void linearListIn(Vector< T > &a_outputT, const void *const a_inBuf)
Definition: SPMDI.H:226
size_t size() const
Definition: Vector.H:177
static void Error(const char *const a_msg=m_nullString, int m_exitCode=CH_DEFAULT_ERROR_CODE)
Print out message to cerr and exit with the specified exit code.
void linearListOut(void *const a_outBuf, const Vector< T > &a_input)
Definition: SPMDI.H:255
int linearListSize(const Vector< T > &a_input)
Definition: SPMDI.H:287
int procID()
local process ID
void broadcast(T &a_inAndOut, int a_src)
broadcast to every process
Definition: SPMDI.H:204