Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

search.txx

Go to the documentation of this file.
00001 
00002 #ifdef __DEBUG__
00003 #ifndef __DEBUG_PAR__
00004 #define __DEBUG_PAR__
00005 #endif
00006 #endif
00007 
00014 namespace par {
00015         
00016         template <typename T>
00017         int maxLowerBound(const std::vector<T> & keys, const std::vector<T> & searchList,
00018 std::vector<T> & results, MPI_Comm comm) {
00019                 PROF_SEARCH_BEGIN
00020 
00021                 int rank, npes;
00022 
00023                 MPI_Comm_size(comm, &npes);
00024                 MPI_Comm_rank(comm, &rank);
00025 
00026                 // allocate memory for the mins array
00027                 std::vector<T> mins (npes);
00028                 assert(!searchList.empty());
00029 
00030                 par::MPI_Allgather<T>( &(*searchList.begin()), &(*mins.begin()), 1, comm);
00031 
00032                 //For each key decide which processor to send to
00033                 unsigned int *part = new unsigned int[keys.size()];
00034                 for ( unsigned int i=0; i<keys.size(); i++ ) {
00035                         //maxLB returns the smallest index in a sorted array such that a[ind] <= key and  a[index +1] > key
00036                         bool found = par::maxLowerBound<T>(mins,keys[i], part+i);
00037                         if ( !found ) {
00038                                 //This key is smaller than the mins from every processor.
00039                                 //No point in searching.
00040                                 part[i] = rank;
00041                         }
00042                 }
00043                 mins.clear();
00044 
00045                 int *numKeysSend = new int[npes];
00046                 int *numKeysRecv = new int[npes];
00047                 for ( int i=0; i<npes; i++ )
00048                         numKeysSend[i] = 0;
00049                 // calculate the number of keys to send ...
00050                 for ( unsigned int i=0; i<keys.size(); i++ )
00051                         numKeysSend[part[i]]++;
00052 
00053                 // Now do an All2All to get numKeysRecv
00054                 par::MPI_Alltoall(numKeysSend, 1, MPI_INT, numKeysRecv, 1, MPI_INT, comm);
00055 
00056                 unsigned int totalKeys=0;       // total number of local keys ...
00057                 for ( int i=0; i<npes; i++ )
00058                         totalKeys += numKeysRecv[i];
00059 
00060                 // create the send and recv buffers ...
00061                 std::vector<T> sendK (keys.size());
00062                 std::vector<T> recvK (totalKeys);
00063                 // the mapping ..
00064                 unsigned int * comm_map = new unsigned int [keys.size()];
00065 
00066                 // Now create sendK
00067                 int *sendOffsets = new int[npes]; sendOffsets[0] = 0;
00068                 int *recvOffsets = new int[npes]; recvOffsets[0] = 0;
00069                 int *numKeysTmp = new int[npes]; numKeysTmp[0] = 0; 
00070 
00071                 // compute offsets ...
00072                 for ( int i=1; i<npes; i++ ) {
00073                         sendOffsets[i] = sendOffsets[i-1] + numKeysSend[i-1];
00074                         recvOffsets[i] = recvOffsets[i-1] + numKeysRecv[i-1];
00075                         numKeysTmp[i] = 0; 
00076                 }
00077 
00078                 for ( unsigned int i=0; i< keys.size(); i++ ) {
00079                         unsigned int ni = numKeysTmp[part[i]];
00080                         numKeysTmp[part[i]]++;
00081                         // set entry ...
00082                         sendK[sendOffsets[part[i]] + ni] = keys[i];
00083                         // save mapping .. will need it later ...
00084                         comm_map[i] = sendOffsets[part[i]] + ni;
00085                 }
00086                 delete [] part;
00087                 delete [] numKeysTmp;
00088 
00089 
00090                 par::MPI_Alltoallv_sparse((void *)&(*sendK.begin()), numKeysSend,
00091                 sendOffsets,par::Mpi_datatype<T>::value(), 
00092                 &(*recvK.begin()), numKeysRecv, recvOffsets,
00093                 par::Mpi_datatype<T>::value(), comm);
00094 
00095 
00096                 std::vector<T>  resSend (totalKeys);
00097                 std::vector<T>  resRecv (keys.size());
00098 
00099                 //Final local search.
00100                 for ( unsigned int i=0; i<totalKeys;i++) {
00101                         unsigned int idx;
00102                         bool found = par::maxLowerBound<T>( searchList, recvK[i], &idx );
00103                         if(found) {
00104                                 resSend[i] = searchList[idx];
00105                         }
00106                 }//end for i
00107 
00108                 //Exchange Results
00109                 //Return what you received in the earlier communication.
00110                 par::MPI_Alltoallv_sparse((void*)&(*resSend.begin()), numKeysRecv,
00111                 recvOffsets,par::Mpi_datatype<T>::value(), 
00112                 &(*resRecv.begin()), numKeysSend, sendOffsets,
00113                 par::Mpi_datatype<T>::value(), comm);
00114 
00115                 delete [] sendOffsets;
00116                 delete [] recvOffsets;
00117                 delete [] numKeysSend;
00118                 delete [] numKeysRecv;
00119 
00120                 for ( unsigned int i=0; i < keys.size(); i++ ) {
00121                         results[i] = resRecv[comm_map[i]];  
00122                 }//end for
00123 
00124                 // Clean up ...
00125                 delete [] comm_map;
00126 
00127                 PROF_SEARCH_END
00128         }
00129 
00130 
00131 }//end namespace
00132 

Generated on Tue Mar 24 16:14:03 2009 for DENDRO by  doxygen 1.3.9.1