libMesh::Parallel::Sort< KeyType, IdxType > Class Template Reference
#include <parallel_sort.h>
Public Member Functions | |
| Sort (std::vector< KeyType > &d, const processor_id_type n_procs=libMesh::n_processors(), const processor_id_type proc_id=libMesh::processor_id()) | |
| void | sort () |
| const std::vector< KeyType > & | bin () |
| template<> | |
| void | binsort () |
| template<> | |
| void | communicate_bins () |
Private Member Functions | |
| void | binsort () |
| void | communicate_bins () |
| void | sort_local_bin () |
Private Attributes | |
| const processor_id_type | _n_procs |
| const processor_id_type | _proc_id |
| bool | _bin_is_sorted |
| std::vector< KeyType > & | _data |
| std::vector< IdxType > | _local_bin_sizes |
| std::vector< KeyType > | _my_bin |
Detailed Description
template<typename KeyType, typename IdxType = unsigned int>
class libMesh::Parallel::Sort< KeyType, IdxType >
The parallel sorting method is templated on the type of data which is to be sorted. It may later be templated on other things if we are ambitious. This class knows about MPI, and knows how many processors there are. It is responsible for transmitting data between the processors and ensuring that the data is properly sorted between all the processors. We assume that a Sort is instantiated on all processors.
Definition at line 47 of file parallel_sort.h.
Constructor & Destructor Documentation
| libMesh::Parallel::Sort< KeyType, IdxType >::Sort | ( | std::vector< KeyType > & | d, | |
| const processor_id_type | n_procs = libMesh::n_processors(), |
|||
| const processor_id_type | proc_id = libMesh::processor_id() | |||
| ) | [inline] |
Constructor takes the number of processors, the processor id, and a reference to a vector of data to be sorted. This vector is sorted by the constructor, therefore, construction of a Sort object takes O(nlogn) time, where n is the length of the vector.
Definition at line 44 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs, and libMesh::Parallel::Sort< KeyType, IdxType >::sort().
00046 : 00047 _n_procs(n_procs), 00048 _proc_id(proc_id), 00049 _bin_is_sorted(false), 00050 _data(d) 00051 { 00052 std::sort(_data.begin(), _data.end()); 00053 00054 // Allocate storage 00055 _local_bin_sizes.resize(_n_procs); 00056 }
Member Function Documentation
| const std::vector< KeyType > & libMesh::Parallel::Sort< KeyType, IdxType >::bin | ( | ) | [inline] |
Return a constant reference to _my_bin. This allows us to do things like check if sorting was successful by printing _my_bin.
Definition at line 355 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_bin_is_sorted, libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin, and libMesh::out.
Referenced by libMesh::MeshCommunication::assign_global_indices(), and libMesh::MeshCommunication::find_global_indices().
00356 { 00357 if (!_bin_is_sorted) 00358 { 00359 libMesh::out << "Warning! Bin is not yet sorted!" << std::endl; 00360 } 00361 00362 return _my_bin; 00363 }
| void libMesh::Parallel::Sort< Hilbert::HilbertIndices, unsigned int >::binsort | ( | ) | [inline] |
Definition at line 133 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs, libMesh::Parallel::BinSorter< KeyType, IdxType >::binsort(), libMesh::COMM_WORLD, and libMesh::Parallel::BinSorter< KeyType, IdxType >::sizeof_bin().
00134 { 00135 // Find the global min and max from all the 00136 // processors. Do this using MPI_Allreduce. 00137 Hilbert::HilbertIndices 00138 local_min, local_max, 00139 global_min, global_max; 00140 00141 if (_data.empty()) 00142 { 00143 local_min.rack0 = local_min.rack1 = local_min.rack2 = static_cast<Hilbert::inttype>(-1); 00144 local_max.rack0 = local_max.rack1 = local_max.rack2 = 0; 00145 } 00146 else 00147 { 00148 local_min = _data.front(); 00149 local_max = _data.back(); 00150 } 00151 00152 MPI_Op hilbert_max, hilbert_min; 00153 00154 MPI_Op_create ((MPI_User_function*)__hilbert_max_op, true, &hilbert_max); 00155 MPI_Op_create ((MPI_User_function*)__hilbert_min_op, true, &hilbert_min); 00156 00157 // Communicate to determine the global 00158 // min and max for all processors. 00159 MPI_Allreduce(&local_min, 00160 &global_min, 00161 1, 00162 Parallel::StandardType<Hilbert::HilbertIndices>(), 00163 hilbert_min, 00164 libMesh::COMM_WORLD); 00165 00166 MPI_Allreduce(&local_max, 00167 &global_max, 00168 1, 00169 Parallel::StandardType<Hilbert::HilbertIndices>(), 00170 hilbert_max, 00171 libMesh::COMM_WORLD); 00172 00173 MPI_Op_free (&hilbert_max); 00174 MPI_Op_free (&hilbert_min); 00175 00176 // Bin-Sort based on the global min and max 00177 Parallel::BinSorter<Hilbert::HilbertIndices> bs(_data); 00178 bs.binsort(_n_procs, global_max, global_min); 00179 00180 // Now save the local bin sizes in a vector so 00181 // we don't have to keep around the BinSorter. 00182 for (processor_id_type i=0; i<_n_procs; ++i) 00183 _local_bin_sizes[i] = bs.sizeof_bin(i); 00184 }
| void libMesh::Parallel::Sort< KeyType, IdxType >::binsort | ( | ) | [inline, private] |
Sorts the local data into bins across all processors. Right now it constructs a BenSorter<KeyType> object. In the future this could be a template parameter.
Definition at line 99 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs, libMesh::Parallel::BinSorter< KeyType, IdxType >::binsort(), libMesh::CommWorld, libMesh::Parallel::Communicator::max(), and libMesh::Parallel::BinSorter< KeyType, IdxType >::sizeof_bin().
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::sort().
00100 { 00101 // Find the global min and max from all the 00102 // processors. 00103 std::vector<KeyType> global_min_max(2); 00104 00105 // Insert the local min and max for this processor 00106 global_min_max[0] = -_data.front(); 00107 global_min_max[1] = _data.back(); 00108 00109 // Communicate to determine the global 00110 // min and max for all processors. 00111 CommWorld.max(global_min_max); 00112 00113 // Multiply the min by -1 to obtain the true min 00114 global_min_max[0] *= -1; 00115 00116 // Bin-Sort based on the global min and max 00117 Parallel::BinSorter<KeyType> bs(_data); 00118 bs.binsort(_n_procs, global_min_max[1], global_min_max[0]); 00119 00120 // Now save the local bin sizes in a vector so 00121 // we don't have to keep around the BinSorter. 00122 for (processor_id_type i=0; i<_n_procs; ++i) 00123 _local_bin_sizes[i] = bs.sizeof_bin(i); 00124 }
| void libMesh::Parallel::Sort< Hilbert::HilbertIndices, unsigned int >::communicate_bins | ( | ) | [inline] |
Definition at line 262 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin, libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs, libMesh::Parallel::Sort< KeyType, IdxType >::_proc_id, and libMesh::COMM_WORLD.
00263 { 00264 // Create storage for the global bin sizes. This 00265 // is the number of keys which will be held in 00266 // each bin over all processors. 00267 std::vector<unsigned int> global_bin_sizes(_n_procs); 00268 00269 libmesh_assert_equal_to (_local_bin_sizes.size(), global_bin_sizes.size()); 00270 00271 // Sum to find the total number of entries in each bin. 00272 // This is stored in global_bin_sizes. Note, we 00273 // explicitly know that we are communicating MPI_UNSIGNED's here. 00274 MPI_Allreduce(&_local_bin_sizes[0], 00275 &global_bin_sizes[0], 00276 _n_procs, 00277 MPI_UNSIGNED, 00278 MPI_SUM, 00279 libMesh::COMM_WORLD); 00280 00281 // Create a vector to temporarily hold the results of MPI_Gatherv 00282 // calls. The vector dest may be saved away to _my_bin depending on which 00283 // processor is being MPI_Gatherv'd. 00284 std::vector<Hilbert::HilbertIndices> sendbuf, dest; 00285 00286 unsigned int local_offset = 0; 00287 00288 for (unsigned int i=0; i<_n_procs; ++i) 00289 { 00290 // Vector to receive the total bin size for each 00291 // processor. Processor i's bin size will be 00292 // held in proc_bin_size[i] 00293 std::vector<unsigned int> proc_bin_size(_n_procs); 00294 00295 // Find the number of contributions coming from each 00296 // processor for this bin. Note: Allgather combines 00297 // the MPI_Gather and MPI_Bcast operations into one. 00298 // Note: Here again we know that we are communicating 00299 // MPI_UNSIGNED's so there is no need to check the MPI_traits. 00300 MPI_Allgather(&_local_bin_sizes[i], // Source: # of entries on this proc in bin i 00301 1, // Number of items to gather 00302 MPI_UNSIGNED, 00303 &proc_bin_size[0], // Destination: Total # of entries in bin i 00304 1, 00305 MPI_UNSIGNED, 00306 libMesh::COMM_WORLD); 00307 00308 // Compute the offsets into my_bin for each processor's 00309 // portion of the bin. These are basically partial sums 00310 // of the proc_bin_size vector. 00311 std::vector<unsigned int> displacements(_n_procs); 00312 for (unsigned int j=1; j<_n_procs; ++j) 00313 displacements[j] = proc_bin_size[j-1] + displacements[j-1]; 00314 00315 // Resize the destination buffer 00316 dest.resize (global_bin_sizes[i]); 00317 00318 MPI_Gatherv((_data.size() > local_offset) ? 00319 &_data[local_offset] : 00320 NULL, // Points to the beginning of the bin to be sent 00321 _local_bin_sizes[i], // How much data is in the bin being sent. 00322 Parallel::StandardType<Hilbert::HilbertIndices>(), // The data type we are sorting 00323 (dest.empty()) ? 00324 NULL : 00325 &dest[0], // Enough storage to hold all bin contributions 00326 (int*) &proc_bin_size[0], // How much is to be received from each processor 00327 (int*) &displacements[0], // Offsets into the receive buffer 00328 Parallel::StandardType<Hilbert::HilbertIndices>(), // The data type we are sorting 00329 i, // The root process (we do this once for each proc) 00330 libMesh::COMM_WORLD); 00331 00332 // Copy the destination buffer if it 00333 // corresponds to the bin for this processor 00334 if (i == _proc_id) 00335 _my_bin = dest; 00336 00337 // Increment the local offset counter 00338 local_offset += _local_bin_sizes[i]; 00339 } 00340 }
| void libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins | ( | ) | [inline, private] |
Communicates the bins from each processor to the appropriate processor. By the time this function is finished, each processor will hold only its own bin(s).
Definition at line 190 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin, libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs, libMesh::Parallel::Sort< KeyType, IdxType >::_proc_id, libMesh::Parallel::allgather(), libMesh::COMM_WORLD, libMesh::CommWorld, and libMesh::Parallel::Communicator::sum().
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::sort().
00191 { 00192 #ifdef LIBMESH_HAVE_MPI 00193 // Create storage for the global bin sizes. This 00194 // is the number of keys which will be held in 00195 // each bin over all processors. 00196 std::vector<IdxType> global_bin_sizes = _local_bin_sizes; 00197 00198 // Sum to find the total number of entries in each bin. 00199 CommWorld.sum(global_bin_sizes); 00200 00201 // Create a vector to temporarily hold the results of MPI_Gatherv 00202 // calls. The vector dest may be saved away to _my_bin depending on which 00203 // processor is being MPI_Gatherv'd. 00204 std::vector<KeyType> dest; 00205 00206 IdxType local_offset = 0; 00207 00208 for (processor_id_type i=0; i<_n_procs; ++i) 00209 { 00210 // Vector to receive the total bin size for each 00211 // processor. Processor i's bin size will be 00212 // held in proc_bin_size[i] 00213 std::vector<IdxType> proc_bin_size; 00214 00215 // Find the number of contributions coming from each 00216 // processor for this bin. Note: allgather combines 00217 // the MPI_Gather and MPI_Bcast operations into one. 00218 Parallel::allgather(_local_bin_sizes[i], proc_bin_size); 00219 00220 // Compute the offsets into my_bin for each processor's 00221 // portion of the bin. These are basically partial sums 00222 // of the proc_bin_size vector. 00223 std::vector<IdxType> displacements(_n_procs); 00224 for (processor_id_type j=1; j<_n_procs; ++j) 00225 displacements[j] = proc_bin_size[j-1] + displacements[j-1]; 00226 00227 // Resize the destination buffer 00228 dest.resize (global_bin_sizes[i]); 00229 00230 MPI_Gatherv((_data.size() > local_offset) ? 00231 &_data[local_offset] : 00232 NULL, // Points to the beginning of the bin to be sent 00233 _local_bin_sizes[i], // How much data is in the bin being sent. 00234 Parallel::StandardType<KeyType>(), // The data type we are sorting 00235 (dest.empty()) ? 00236 NULL : 00237 &dest[0], // Enough storage to hold all bin contributions 00238 (int*) &proc_bin_size[0], // How much is to be received from each processor 00239 (int*) &displacements[0], // Offsets into the receive buffer 00240 Parallel::StandardType<KeyType>(), // The data type we are sorting 00241 i, // The root process (we do this once for each proc) 00242 libMesh::COMM_WORLD); 00243 00244 // Copy the destination buffer if it 00245 // corresponds to the bin for this processor 00246 if (i == _proc_id) 00247 _my_bin = dest; 00248 00249 // Increment the local offset counter 00250 local_offset += _local_bin_sizes[i]; 00251 } 00252 #endif // LIBMESH_HAVE_MPI 00253 }
| void libMesh::Parallel::Sort< KeyType, IdxType >::sort | ( | ) | [inline] |
This is the only method which needs to be called by the user. Its only responsibility is to call three private methods in the correct order.
Definition at line 61 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_bin_is_sorted, libMesh::Parallel::Sort< KeyType, IdxType >::_data, libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes, libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin, libMesh::Parallel::Communicator::allgather(), libMesh::Parallel::Sort< KeyType, IdxType >::binsort(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), libMesh::CommWorld, libMesh::n_processors(), libMesh::Parallel::Sort< KeyType, IdxType >::sort_local_bin(), and libMesh::Parallel::Communicator::sum().
Referenced by libMesh::MeshCommunication::assign_global_indices(), libMesh::MeshCommunication::find_global_indices(), libMesh::Parallel::Sort< KeyType, IdxType >::Sort(), and libMesh::Parallel::Sort< KeyType, IdxType >::sort_local_bin().
00062 { 00063 // Find the global data size. The sorting 00064 // algorithms assume they have a range to 00065 // work with, so catch the degenerate cases here 00066 IdxType global_data_size = libmesh_cast_int<IdxType>(_data.size()); 00067 00068 CommWorld.sum (global_data_size); 00069 00070 if (global_data_size < 2) 00071 { 00072 // the entire global range is either empty 00073 // or contains only one element 00074 _my_bin = _data; 00075 00076 CommWorld.allgather (static_cast<IdxType>(_my_bin.size()), 00077 _local_bin_sizes); 00078 } 00079 else 00080 { 00081 if (libMesh::n_processors() > 1) 00082 { 00083 this->binsort(); 00084 this->communicate_bins(); 00085 } 00086 else 00087 _my_bin = _data; 00088 00089 this->sort_local_bin(); 00090 } 00091 00092 // Set sorted flag to true 00093 _bin_is_sorted = true; 00094 }
| void libMesh::Parallel::Sort< KeyType, IdxType >::sort_local_bin | ( | ) | [inline, private] |
After all the bins have been communicated, we can sort our local bin. This is nothing more than a call to std::sort
Definition at line 347 of file parallel_sort.C.
References libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin, and libMesh::Parallel::Sort< KeyType, IdxType >::sort().
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::sort().
Member Data Documentation
bool libMesh::Parallel::Sort< KeyType, IdxType >::_bin_is_sorted [private] |
Flag which lets you know if sorting is complete
Definition at line 93 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::bin(), and libMesh::Parallel::Sort< KeyType, IdxType >::sort().
std::vector<KeyType>& libMesh::Parallel::Sort< KeyType, IdxType >::_data [private] |
The raw, unsorted data which will need to be sorted (in parallel) across all processors.
Definition at line 100 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::binsort(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), libMesh::Parallel::Sort< KeyType, IdxType >::sort(), and libMesh::Parallel::Sort< KeyType, IdxType >::Sort().
std::vector<IdxType> libMesh::Parallel::Sort< KeyType, IdxType >::_local_bin_sizes [private] |
Vector which holds the size of each bin on this processor. It has size equal to _n_procs.
Definition at line 107 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::binsort(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), libMesh::Parallel::Sort< KeyType, IdxType >::sort(), and libMesh::Parallel::Sort< KeyType, IdxType >::Sort().
std::vector<KeyType> libMesh::Parallel::Sort< KeyType, IdxType >::_my_bin [private] |
The bin which will eventually be held by this processor. It may be shorter or longer than _data. It will be dynamically resized when it is needed.
Definition at line 115 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::bin(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), libMesh::Parallel::Sort< KeyType, IdxType >::sort(), and libMesh::Parallel::Sort< KeyType, IdxType >::sort_local_bin().
const processor_id_type libMesh::Parallel::Sort< KeyType, IdxType >::_n_procs [private] |
The number of processors to work with.
Definition at line 83 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::binsort(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), and libMesh::Parallel::Sort< KeyType, IdxType >::Sort().
const processor_id_type libMesh::Parallel::Sort< KeyType, IdxType >::_proc_id [private] |
The identity of this processor.
Definition at line 88 of file parallel_sort.h.
Referenced by libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins().
The documentation for this class was generated from the following files:
Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:45 UTC
Hosted By: