00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _SPMDI_H_
00012 #define _SPMDI_H_
00013
00014 #include "memtrack.H"
00015 #include "BaseNamespaceHeader.H"
00016
00017
00018
00019 template <class T>
00020 int linearSize(const T& inputT)
00021 {
00022 return inputT.linearSize();
00023 }
00024
00025 template <class T>
00026 void linearIn(T& a_outputT, const void* const inBuf)
00027 {
00028 a_outputT.linearIn(inBuf);
00029 }
00030
00031 template <class T>
00032 void linearOut(void* const a_outBuf, const T& inputT)
00033 {
00034 inputT.linearOut(a_outBuf);
00035 }
00036
00037 #ifdef CH_MPI
00038
00039 extern void AttachDebugger(int);
00040
00041
00042
00043 template <class T>
00044 inline void
00045 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00046 {
00047 CH_assert (a_dest >= 0);
00048 CH_assert(a_dest < numProc());
00049
00050 int isize = linearSize(a_input);
00051
00052
00053 void* loclBuf = mallocMT(isize);
00054 if(loclBuf == NULL)
00055 MayDay::Error("out of memory in gather 1");
00056
00057
00058 linearOut(loclBuf, a_input);
00059
00060 int nProcess = numProc();
00061 int sendCount = 1;
00062 int recdCount = 1;
00063
00064
00065 int* vectSize = NULL;
00066 int* vectDisp = NULL;
00067 void* sendBuf = static_cast<void*>(&isize);
00068
00069 if(procID() == a_dest)
00070 {
00071 vectSize = new int[nProcess];
00072 vectDisp = new int[nProcess];
00073 }
00074
00075 int result1 = MPI_Gather(sendBuf, sendCount, MPI_INT,
00076 vectSize,recdCount, MPI_INT,
00077 a_dest, Chombo_MPI::comm);
00078
00079 if(result1 != MPI_SUCCESS)
00080 MayDay::Error("Gather<T> failed in MPI_Gather 1");
00081
00082
00083 void* recdBuf = NULL;
00084 if(procID() == a_dest)
00085 {
00086 int itotsize=0;
00087 for(int iproc = 0; iproc < nProcess; iproc++)
00088 {
00089 vectDisp[iproc] = itotsize;
00090 itotsize += vectSize[iproc];
00091 }
00092 recdBuf = mallocMT(itotsize);
00093 if(recdBuf == NULL)
00094 MayDay::Error("out of memory in gather 2");
00095 }
00096
00097
00098 int result2 = MPI_Gatherv(loclBuf, isize, MPI_BYTE,
00099 recdBuf, vectSize, vectDisp, MPI_BYTE,
00100 a_dest, Chombo_MPI::comm);
00101 if(result2 != MPI_SUCCESS)
00102 MayDay::Error("Gather<T> failed in MPI_Gather 2");
00103
00104 if(procID() == a_dest)
00105 {
00106
00107 int ioffset = 0;
00108 a_outVec.resize(nProcess);
00109
00110 char* arithPtr = (char*)recdBuf;
00111 for(int iproc = 0; iproc < nProcess; iproc++)
00112 {
00113 ioffset = vectDisp[iproc];
00114 char* thisProcBuf = arithPtr + ioffset;
00115 linearIn(a_outVec[iproc], thisProcBuf);
00116 }
00117
00118
00119 delete[] vectSize;
00120 delete[] vectDisp;
00121 freeMT(recdBuf);
00122 }
00123
00124
00125 freeMT(loclBuf);
00126 }
00127
00128
00129
00130
00131 template <class T>
00132 inline void
00133 broadcast(T& a_inAndOut, int a_src)
00134 {
00135 CH_assert (a_src >= 0);
00136 CH_assert(a_src < numProc());
00137 int isize;
00138 if(procID() == a_src)
00139 isize = linearSize(a_inAndOut);
00140
00141 MPI_Bcast(&isize, 1, MPI_INT, a_src, Chombo_MPI::comm);
00142
00143 void* broadBuf = mallocMT(isize);
00144
00145 if(broadBuf == NULL)
00146 MayDay::Error("out of memory in broadcast");
00147
00148
00149 if(procID() == a_src)
00150 linearOut(broadBuf, a_inAndOut);
00151
00152
00153 MPI_Bcast(broadBuf, isize, MPI_BYTE, a_src, Chombo_MPI::comm);
00154
00155 if(procID()==a_src){
00156 CH_MaxMPISendSize = Max<long long>(CH_MaxMPISendSize, isize);
00157 } else {
00158 CH_MaxMPIRecvSize = Max<long long>(CH_MaxMPIRecvSize, isize);
00159 }
00160
00161 if(procID() != a_src)
00162 linearIn(a_inAndOut, broadBuf);
00163
00164
00165 freeMT(broadBuf);
00166 }
00167
00168
00169
00170
00171 inline void
00172 barrier(void)
00173 {
00174 MPI_Barrier(Chombo_MPI::comm);
00175 }
00176
00177 #else
00178
00179
00180
00181 template <class T>
00182 inline void
00183 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00184 {
00185 a_outVec.resize(1);
00186 a_outVec[0] = a_input;
00187 }
00188
00189
00190
00191 template <class T>
00192 inline void
00193 broadcast(T& a_inAndOut, int a_src)
00194 {
00195
00196 }
00197
00198
00199
00200 inline void
00201 barrier(void)
00202 {
00203
00204 }
00205
00206 #endif //the mpi thing
00207
00208
00209
00210
00211
00212
00213 template <class T>
00214 void
00215 linearListIn(Vector<T>& a_outputT, const void* const a_inBuf)
00216 {
00217
00218 const int* const intBuf = (int*)a_inBuf;
00219 int vecsize = intBuf[0];
00220 Vector<int> vecOffset(vecsize);
00221
00222 for(int ivec = 0; ivec < vecsize; ivec++)
00223 {
00224 vecOffset[ivec] = intBuf[ivec+1];
00225 }
00226
00227
00228
00229
00230
00231
00232 a_outputT.resize(vecsize);
00233 const char* const charbuf = (char*)a_inBuf;
00234 for(int ivec = 0; ivec < vecsize; ivec++)
00235 {
00236 const char* const dataLoc = charbuf + vecOffset[ivec];
00237 linearIn(a_outputT[ivec], dataLoc);
00238 }
00239 }
00240
00241
00242 template <class T>
00243 void
00244 linearListOut(void* const a_outBuf, const Vector<T>& a_input)
00245 {
00246
00247 int* const intBuf = (int*)a_outBuf;
00248 intBuf[0] = a_input.size();
00249 int vecsize = intBuf[0];
00250 Vector<int> vecOffset(vecsize);
00251
00252
00253 int ioffset = (vecsize+1)*sizeof(int);
00254 for(int ivec = 0; ivec < vecsize; ivec++)
00255 {
00256 intBuf[ivec+1] = ioffset;
00257 vecOffset[ivec] = ioffset;
00258 ioffset += linearSize(a_input[ivec]);
00259 }
00260
00261
00262
00263
00264
00265 char* const charBuf = (char*)a_outBuf;
00266 for(int ivec = 0; ivec < vecsize; ivec++)
00267 {
00268 char* const dataLoc = charBuf + vecOffset[ivec];
00269 linearOut(dataLoc, a_input[ivec]);
00270 }
00271 }
00272
00273
00274 template <class T>
00275 int
00276 linearListSize(const Vector<T>& a_input)
00277 {
00278
00279
00280
00281 int itotsize = (a_input.size() + 1)*sizeof(int);
00282 for(int ivec = 0; ivec < a_input.size(); ivec++)
00283 {
00284 itotsize += linearSize(a_input[ivec]);
00285 }
00286 return itotsize;
00287 }
00288
00289 #include "BaseNamespaceFooter.H"
00290
00291 #endif