Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

SPMDI.H

Go to the documentation of this file.
00001 /* _______              __
00002   / ___/ /  ___  __ _  / /  ___
00003  / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00004  \___/_//_/\___/_/_/_/_.__/\___/ 
00005 */
00006 //
00007 // This software is copyright (C) by the Lawrence Berkeley
00008 // National Laboratory.  Permission is granted to reproduce
00009 // this software for non-commercial purposes provided that
00010 // this notice is left intact.
00011 // 
00012 // It is acknowledged that the U.S. Government has rights to
00013 // this software under Contract DE-AC03-765F00098 between
00014 // the U.S.  Department of Energy and the University of
00015 // California.
00016 //
00017 // This software is provided as a professional and academic
00018 // contribution for joint exchange. Thus it is experimental,
00019 // is provided ``as is'', with no warranties of any kind
00020 // whatsoever, no support, no promise of updates, or printed
00021 // documentation. By using this software, you acknowledge
00022 // that the Lawrence Berkeley National Laboratory and
00023 // Regents of the University of California shall have no
00024 // liability with respect to the infringement of other
00025 // copyrights by any part of this software.
00026 //
00027 
00028 #ifndef _SPMDI_H_
00029 #define _SPMDI_H_
00030 
00031 #ifdef MPI
00032 
00033 /*****************************/
00034 //gather a_input into a a_outVec
00035 /*****************************/
00036 template <class T>
00037 inline void 
00038 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00039 {
00040   assert (a_dest >= 0);
00041   assert(a_dest <  numProc());
00042   //now THIS size lives on THIS processor
00043   int isize = linearSize(a_input);
00044     
00045   //make stuff for linearout
00046   void* loclBuf = malloc(isize);
00047   if(loclBuf == NULL)
00048     MayDay::Error("out of memory in gather 1");
00049     
00050   //put linearized T into its proper buffer
00051   linearOut(loclBuf, a_input);
00052 
00053 
00054   int nProcess = numProc(); 
00055   int sendCount = 1;
00056   int recdCount = 1;
00057     
00058   //need to gather isizes onto processor a_dest
00059   int* vectSize = NULL;
00060   int* vectDisp = NULL;
00061   void* sendBuf = static_cast<void*>(&isize);
00062   //allocate received buffer
00063   if(procID() == a_dest)
00064     {
00065       vectSize = new int[nProcess];
00066       vectDisp = new int[nProcess];
00067     }
00068 
00069   int result1 = MPI_Gather(sendBuf, sendCount, MPI_INT, 
00070                            vectSize,recdCount, MPI_INT,
00071                            a_dest,  Chombo_MPI::comm);
00072 
00073   if(result1 != MPI_SUCCESS)
00074     MayDay::Error("Gather<T> failed in MPI_Gather 1");
00075 
00076   //make memory for gather, linearin
00077   void* recdBuf = NULL;
00078   if(procID() == a_dest)
00079     {
00080       int itotsize=0;
00081       for(int iproc = 0; iproc < nProcess; iproc++)
00082         {
00083           vectDisp[iproc] = itotsize;
00084           itotsize += vectSize[iproc];
00085         }
00086       recdBuf = malloc(itotsize);
00087       if(recdBuf == NULL)
00088         MayDay::Error("out of memory in gather 2");
00089     }
00090 
00091   //gather data 
00092   int result2 = MPI_Gatherv(loclBuf, isize, MPI_BYTE, 
00093                             recdBuf, vectSize, vectDisp, MPI_BYTE,
00094                             a_dest, Chombo_MPI::comm);
00095   if(result2 != MPI_SUCCESS)
00096     MayDay::Error("Gather<T> failed in MPI_Gather 2");
00097 
00098 
00099   if(procID() == a_dest)
00100     {
00101       //calculate offset into array for current processor
00102       int ioffset = 0;
00103       a_outVec.resize(nProcess);
00104       //need to cast to char* to do pointer arithmetic
00105       char* arithPtr = (char*)recdBuf;
00106       for(int iproc = 0; iproc < nProcess; iproc++)
00107         {
00108           ioffset = vectDisp[iproc];
00109           char* thisProcBuf = arithPtr + ioffset;
00110           linearIn(a_outVec[iproc], thisProcBuf);
00111         }
00112 
00113       //delete memory for dest-specific arrays
00114       delete[] vectSize;
00115       delete[] vectDisp;
00116       free(recdBuf);
00117     }
00118 
00119   //delete memory for local buffer
00120   free(loclBuf);
00121 }
00122 
00123 
00124 /*****************************/
00125 //broadcast T everywhere
00126 /*****************************/
00127 template <class T>
00128 inline void 
00129 broadcast(T& a_inAndOut,  int a_src)
00130 {
00131   assert (a_src >= 0);
00132   assert(a_src <  numProc());
00133   int isize;  
00134   if(procID() == a_src)
00135     isize = linearSize(a_inAndOut);
00136 
00137   MPI_Bcast(&isize, 1, MPI_INT, a_src, Chombo_MPI::comm);
00138 
00139   void* broadBuf = malloc(isize);
00140 
00141   if(broadBuf == NULL)
00142     MayDay::Error("out of memory in broadcast");
00143 
00144   //take inAndOut from src and put it into broadBuf
00145   if(procID() == a_src)
00146       linearOut(broadBuf, a_inAndOut);
00147 
00148   //broadcast broadBuf to all procs
00149   MPI_Bcast(broadBuf, isize, MPI_BYTE, a_src, Chombo_MPI::comm);
00150     
00151   //take broadBuf and put back into inAndOut if not src
00152   if(procID() != a_src)
00153       linearIn(a_inAndOut, broadBuf);
00154 
00155   //delete memory for buffer
00156   free(broadBuf);
00157 }
00158 
00159 #else
00160 /*****************************/
00161 //non-mpi version
00162 /*****************************/
00163 template <class T>
00164 inline void 
00165 gather(Vector<T>& a_outVec, const T& a_input, int a_dest)
00166 {
00167   a_outVec.resize(1);
00168   a_outVec[0] = a_input;
00169 }
00170 /*****************************/
00171 //non-mpi version
00172 /*****************************/
00173 template <class T>
00174 inline void 
00175 broadcast(T& a_inAndOut,  int a_src)
00176 {
00177   //nothing to do.  in and out are the same with one proc
00178 }
00179 
00180 #endif //the mpi thing
00181 
00182 //*************************************
00183 //These should work independent of MPI
00184 //*************************************
00185 
00186 //Vector<T> specialization of linearIn
00187 template <class T>
00188 void 
00189 linearListIn(Vector<T>& a_outputT, const void* const a_inBuf)
00190 {
00191   //first entry is the size of the vector
00192   const int* const intBuf = (int*)a_inBuf;
00193   int vecsize = intBuf[0];
00194   Vector<int> vecOffset(vecsize);
00195   //next vecsize entries are offsets of data into buffer
00196   for(int ivec = 0; ivec < vecsize; ivec++)
00197     {
00198       vecOffset[ivec] = intBuf[ivec+1];
00199     }
00200   //next vecsize entries are the actual data
00201   //yes I could do this in one loop but that would 
00202   // either 
00203   // a) make it less symmetric with linearOut 
00204   // and/or
00205   // b) make both of them far less readable
00206   a_outputT.resize(vecsize);
00207   const char* const charbuf = (char*)a_inBuf;
00208   for(int ivec = 0; ivec < vecsize; ivec++)
00209     {
00210       const char* const dataLoc = charbuf + vecOffset[ivec];
00211       linearIn(a_outputT[ivec], dataLoc);
00212     }
00213 }
00214 
00215 //Vector<T> specialization of linearOut
00216 template <class T>
00217 void 
00218 linearListOut(void* const a_outBuf, const Vector<T>& a_input)
00219 {
00220   //first entry is the size of the vector
00221   int* const intBuf = (int*)a_outBuf;
00222   intBuf[0] = a_input.size();
00223   int vecsize = intBuf[0];
00224   Vector<int> vecOffset(vecsize);
00225   //next vecsize entries are offsets of data into buffer
00226   //next vecsize entries are the actual data
00227   int ioffset = (vecsize+1)*sizeof(int);
00228   for(int ivec = 0; ivec < vecsize; ivec++)
00229     {
00230       intBuf[ivec+1] = ioffset; 
00231       vecOffset[ivec] = ioffset; 
00232       ioffset += linearSize(a_input[ivec]);
00233     }
00234   //yes I could do this in one loop but that would 
00235   // either 
00236   // a) make it less symmetric with linearIn
00237   // and/or
00238   // b) make both of them far less readable
00239   char* const charBuf = (char*)a_outBuf;
00240   for(int ivec = 0; ivec < vecsize; ivec++)
00241     {
00242       char* const dataLoc = charBuf + vecOffset[ivec];
00243       linearOut(dataLoc, a_input[ivec]);
00244     }
00245 }
00246 
00247 //Vector<T> specialization of linearSize
00248 template <class T>
00249 int 
00250 linearListSize(const Vector<T>& a_input)
00251 {
00252   //first entry is the size of the vector (int)
00253   //next vecsize entries are offsets of data into buffer (int)
00254   //next vecsize entries are the actual data
00255   int itotsize = (a_input.size() + 1)*sizeof(int);
00256   for(int ivec = 0; ivec < a_input.size(); ivec++)
00257     {
00258       itotsize += linearSize(a_input[ivec]);
00259     }
00260   return itotsize;
00261 }
00262 
00263 #endif

Generated on Wed Apr 16 14:31:05 2003 for EBChombo by doxygen1.2.16