diff --git a/include/ALL.hpp b/include/ALL.hpp index a7c9cbf40c756ffb5c67734b881c5546acc6a052..31f9a3fcec514bc1e930abc2374c8661e34b9656 100644 --- a/include/ALL.hpp +++ b/include/ALL.hpp @@ -205,6 +205,8 @@ template <class T, class W> class ALL #endif private: + ALL_LB_t load_balancer_type; + // outer cuboid encasing the domain (for cuboid domains identical to domain) // defined by front left lower [0][*] and back upper right points [1][*] // where * is 0,...,dim-1 @@ -268,9 +270,44 @@ template <class T, class W> class ALL template <class T, class W> ALL<T,W>::~ALL() { - if (outline) delete outline; - if (work_array) delete work_array; + delete outline; + delete work_array; proc_grid_set = false; + + try + { + switch(load_balancer_type) + { + case ALL_LB_t::TENSOR: + delete (ALL_Tensor_LB<T,W>*)balancer; + break; + case ALL_LB_t::STAGGERED: + delete (ALL_Staggered_LB<T,W>*)balancer; + break; + case ALL_LB_t::UNSTRUCTURED: + delete (ALL_Unstructured_LB<T,W>*)balancer; + break; + case ALL_LB_t::VORONOI: +#ifdef ALL_VORONOI + delete (ALL_Voronoi_LB<T,W>*)balancer; +#endif + break; + case ALL_LB_t::HISTOGRAM: + delete (ALL_Histogram_LB<T,W>*)balancer; + break; + default: + throw ALL_Invalid_Argument_Exception( + __FILE__, + __func__, + __LINE__, + "Unknown type of loadbalancing passed."); + } + } + catch (ALL_Custom_Exception e) + { + std::cout << e.what() << std::endl; + MPI_Abort(MPI_COMM_WORLD,-1); + } } template <class T, class W> void ALL<T,W>::set_vertices(std::vector<ALL_Point<T>>& inp) @@ -424,7 +461,7 @@ template <class T, class W> void ALL<T,W>::set_communicator(MPI_Comm comm) template <class T, class W> void ALL<T,W>::get_work(W& result) { - result = work_array.at(0); + result = work_array->at(0); } template <class T, class W> void ALL<T,W>::get_work(std::vector<W>& result) @@ -523,6 +560,7 @@ template <class T, class W> void ALL<T,W>::setup(ALL_LB_t method) std::cout << e.what() << std::endl; MPI_Abort(MPI_COMM_WORLD,-1); } + load_balancer_type = method; } template <class T, class W> void ALL<T,W>::setup_balancer(ALL_LB_t method) diff --git a/include/ALL_Staggered.hpp b/include/ALL_Staggered.hpp index 6282d76404f2a7ef20d36563eb3e2a7f23dd11ea..7f66ef852713d5ab49ff4082f746d81912865ed7 100644 --- a/include/ALL_Staggered.hpp +++ b/include/ALL_Staggered.hpp @@ -2,29 +2,29 @@ Copyright 2018 Rene Halver, Forschungszentrum Juelich GmbH, Germany Copyright 2018 Godehard Sutmann, Forschungszentrum Juelich GmbH, Germany -Redistribution and use in source and binary forms, with or without modification, +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or +2. Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may - be used to endorse or promote products derived from this software without +3. Neither the name of the copyright holder nor the names of its contributors may + be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -43,14 +43,14 @@ template <class T, class W> class ALL_Staggered_LB public: ALL_Staggered_LB() {} ALL_Staggered_LB(int d, W w, T g) : dimension(d), - work(w), + work(w), gamma(g) { // need the lower and upper bounds // of the domain for the tensor-based // load-balancing scheme - vertices = new std::vector<T>(6); - shifted_vertices = new std::vector<T>(6); + vertices = std::vector<T>(6); + shifted_vertices = std::vector<T>(6); // global dimension of the system in each coordinate global_dims = new int[3]; // coordinates of the local domain in the system @@ -67,7 +67,7 @@ template <class T, class W> class ALL_Staggered_LB min_size = new T[d]; } - ~ALL_Staggered_LB(); + ~ALL_Staggered_LB(); void set_vertices(T*); @@ -108,10 +108,10 @@ template <class T, class W> class ALL_Staggered_LB W work; // vertices - std::vector<T>* vertices; + std::vector<T> vertices; // vertices after load-balancing shift - std::vector<T>* shifted_vertices; + std::vector<T> shifted_vertices; // MPI values // global communicator @@ -124,7 +124,7 @@ template <class T, class W> class ALL_Staggered_LB int* local_coords; // periodicity of the MPI communicator / system int* periodicity; - + // type for MPI communication MPI_Datatype mpi_data_type_T; MPI_Datatype mpi_data_type_W; @@ -147,26 +147,23 @@ template <class T, class W> class ALL_Staggered_LB template <class T, class W> ALL_Staggered_LB<T,W>::~ALL_Staggered_LB() { - if (vertices) delete vertices; - if (shifted_vertices) delete shifted_vertices; - if (global_dims) delete global_dims; - if (local_coords) delete local_coords; - if (periodicity) delete periodicity; - if (communicators) - { - for (int i = 1; i < 3; ++i) - MPI_Comm_free(communicators + i); - delete communicators; - } - if (n_neighbors) delete n_neighbors; - if (min_size) delete[] min_size; + delete[] global_dims; + delete[] local_coords; + delete[] periodicity; + + for (int i = 1; i < 3; ++i) + MPI_Comm_free(communicators + i); + delete[] communicators; + + delete n_neighbors; + delete[] min_size; } template <class T, class W> void ALL_Staggered_LB<T,W>::get_vertices(T* result) { for (int i = 0; i < 2*dimension; ++i) { - result[i] = vertices->at(i); + result[i] = vertices.at(i); } } @@ -180,7 +177,7 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::get_shifted_vertices(T* { for (int i = 0; i < 2*dimension; ++i) { - result[i] = shifted_vertices->at(i); + result[i] = shifted_vertices.at(i); } } @@ -188,7 +185,7 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::get_shifted_vertices(std { for (int i = 0; i < 2*dimension; ++i) { - result.at(i) = shifted_vertices->at(i); + result.at(i) = shifted_vertices.at(i); } } @@ -197,12 +194,12 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::set_vertices(T* v) { for (int i = 0; i < 2*dimension; ++i) { - vertices->at(i) = v[i]; + vertices.at(i) = v[i]; } } // setup routine for the tensor-based load-balancing scheme -// requires: +// requires: // global_comm (int): cartesian MPI communicator, from // which separate sub communicators // are derived in order to represent @@ -221,11 +218,6 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::setup(MPI_Comm comm) __LINE__, "Cartesian MPI communicator required, passed communicator is not cartesian"); } - - // allocate arrays to correct sizes - global_dims = new int[dimension]; - local_coords = new int[dimension]; - periodicity = new int[dimension]; // store MPI communicator to local variable global_comm = comm; @@ -236,7 +228,7 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::setup(MPI_Comm comm) // get the local rank from the MPI communicator MPI_Cart_rank(global_comm, local_coords, &local_rank); - // create sub-communicators + // create sub-communicators // z-plane MPI_Comm_split(global_comm,local_coords[2],local_coords[0]+local_coords[1]*global_dims[0],&communicators[2]); @@ -263,7 +255,7 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::setup(MPI_Comm comm) "Invalid data type for boundaries given (T)"); } - // determine correct MPI data type for template W + // determine correct MPI data type for template W if (std::is_same<W,double>::value) mpi_data_type_W = MPI_DOUBLE; else if (std::is_same<W,float>::value) mpi_data_type_W = MPI_FLOAT; else if (std::is_same<W,int>::value) mpi_data_type_W = MPI_INT; @@ -287,7 +279,7 @@ template <class T, class W> void ALL_Staggered_LB<T,W>::setup(MPI_Comm comm) neighbors.push_back(rank_left); neighbors.push_back(rank_right); } - + } template<class T, class W> void ALL_Staggered_LB<T,W>::balance() @@ -298,7 +290,7 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::balance() W work_local_plane; // collect work from all processes in the same plane MPI_Allreduce(&work,&work_local_plane,1,mpi_data_type_W,MPI_SUM,communicators[i]); - + // correct right border: W remote_work; @@ -320,8 +312,8 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::balance() // collect size in dimension from right neighbor plane - size = vertices->at(dimension+i) - vertices->at(i); - + size = vertices.at(dimension+i) - vertices.at(i); + MPI_Irecv(&remote_size,1,mpi_data_type_T,rank_right,0,global_comm,&rreq); MPI_Isend(&size,1,mpi_data_type_T,rank_left,0,global_comm,&sreq); MPI_Wait(&sreq,&sstat); @@ -350,7 +342,7 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::balance() // send shift to right neighbors T remote_shift = (T)0; - + MPI_Irecv(&remote_shift,1,mpi_data_type_T,rank_left,0,global_comm,&rreq); MPI_Isend(&shift,1,mpi_data_type_T,rank_right,0,global_comm,&sreq); MPI_Wait(&sreq,&sstat); @@ -358,26 +350,26 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::balance() // for now: test case for simple program - // if a left neighbor exists: shift left border + // if a left neighbor exists: shift left border if (rank_left != MPI_PROC_NULL && local_coords[i] != 0) - shifted_vertices->at(i) = vertices->at(i) + remote_shift; + shifted_vertices.at(i) = vertices.at(i) + remote_shift; else - shifted_vertices->at(i) = vertices->at(i); + shifted_vertices.at(i) = vertices.at(i); // if a right neighbor exists: shift right border if (rank_right != MPI_PROC_NULL && local_coords[i] != global_dims[i]-1) - shifted_vertices->at(dimension+i) = vertices->at(dimension+i) + shift; + shifted_vertices.at(dimension+i) = vertices.at(dimension+i) + shift; else - shifted_vertices->at(dimension+i) = vertices->at(dimension+i); + shifted_vertices.at(dimension+i) = vertices.at(dimension+i); // check if vertices are crossed and throw exception if thing went wrong - if (shifted_vertices->at(dimension+i) < shifted_vertices->at(i)) + if (shifted_vertices.at(dimension+i) < shifted_vertices.at(i)) { std::cout << "ERROR on process: " << local_rank << " " - << vertices->at(i) << " " - << vertices->at(dimension+i) << " " - << shifted_vertices->at(i) << " " - << shifted_vertices->at(dimension+i) << " " + << vertices.at(i) << " " + << vertices.at(dimension+i) << " " + << shifted_vertices.at(i) << " " + << shifted_vertices.at(dimension+i) << " " << remote_shift << " " << shift << " " << remote_size << " " @@ -422,7 +414,7 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() // find X-neighbors MPI_Cart_shift(global_comm,0,1,&rank_left,&rank_right); - // store X-neighbors + // store X-neighbors neighbors.push_back(rank_left); neighbors.push_back(rank_right); @@ -430,8 +422,8 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() MPI_Cart_shift(global_comm,1,1,&rank_left,&rank_right); // collect border information from local column - vertices_loc[0] = shifted_vertices->at(0); - vertices_loc[1] = shifted_vertices->at(dimension); + vertices_loc[0] = shifted_vertices.at(0); + vertices_loc[1] = shifted_vertices.at(dimension); MPI_Allgather(vertices_loc,2,mpi_data_type_T,vertices_rem+2*global_dims[0],2,mpi_data_type_T,communicators[1]); // exchange local column information with upper neighbor in Y direction (cart grid) @@ -456,7 +448,7 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() n_neighbors->at(2) = 0; for (int x = 0; x < global_dims[0]; ++x) { - if ( + if ( ( vertices_rem[2*x] <= vertices_loc[0] && vertices_loc[0] < vertices_rem[2*x+1] ) || ( vertices_rem[2*x] < vertices_loc[1] && vertices_loc[1] <= vertices_rem[2*x+1] ) || ( vertices_rem[2*x] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[2*x+1] && @@ -495,7 +487,7 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() n_neighbors->at(3) = 0; for (int x = 0; x < global_dims[0]; ++x) { - if ( + if ( ( vertices_rem[2*x] <= vertices_loc[0] && vertices_loc[0] < vertices_rem[2*x+1] ) || ( vertices_rem[2*x] < vertices_loc[1] && vertices_loc[1] <= vertices_rem[2*x+1] ) || ( vertices_rem[2*x] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[2*x+1] && @@ -516,10 +508,10 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() MPI_Cart_shift(global_comm,2,1,&rank_left,&rank_right); // collect border information from local column - vertices_loc[0] = shifted_vertices->at(0); - vertices_loc[1] = shifted_vertices->at(dimension); - vertices_loc[2] = shifted_vertices->at(1); - vertices_loc[3] = shifted_vertices->at(1+dimension); + vertices_loc[0] = shifted_vertices.at(0); + vertices_loc[1] = shifted_vertices.at(dimension); + vertices_loc[2] = shifted_vertices.at(1); + vertices_loc[3] = shifted_vertices.at(1+dimension); MPI_Barrier(global_comm); @@ -550,18 +542,18 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() for (int x = 0; x < global_dims[0]; ++x) { if ( - ( + ( ( vertices_rem[4*(x+y*global_dims[0])+2] <= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] ) || ( vertices_rem[4*(x+y*global_dims[0])+2] < vertices_loc[3] && vertices_loc[3] <= vertices_rem[4*(x+y*global_dims[0])+3] ) || - ( vertices_rem[4*(x+y*global_dims[0])+2] >= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] && + ( vertices_rem[4*(x+y*global_dims[0])+2] >= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] && vertices_loc[3] >= vertices_rem[4*(x+y*global_dims[0])+3] ) ) ) if ( - ( + ( ( vertices_rem[4*(x+y*global_dims[0])] <= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] ) || ( vertices_rem[4*(x+y*global_dims[0])] < vertices_loc[1] && vertices_loc[1] <= vertices_rem[4*(x+y*global_dims[0])+1] ) || - ( vertices_rem[4*(x+y*global_dims[0])] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] && + ( vertices_rem[4*(x+y*global_dims[0])] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] && vertices_loc[1] >= vertices_rem[4*(x+y*global_dims[0])+1] ) ) ) @@ -602,18 +594,18 @@ template<class T, class W> void ALL_Staggered_LB<T,W>::find_neighbors() for (int x = 0; x < global_dims[0]; ++x) { if ( - ( + ( ( vertices_rem[4*(x+y*global_dims[0])+2] <= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] ) || ( vertices_rem[4*(x+y*global_dims[0])+2] < vertices_loc[3] && vertices_loc[3] <= vertices_rem[4*(x+y*global_dims[0])+3] ) || - ( vertices_rem[4*(x+y*global_dims[0])+2] >= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] && + ( vertices_rem[4*(x+y*global_dims[0])+2] >= vertices_loc[2] && vertices_loc[2] < vertices_rem[4*(x+y*global_dims[0])+3] && vertices_loc[3] >= vertices_rem[4*(x+y*global_dims[0])+3] ) ) ) if ( - ( + ( ( vertices_rem[4*(x+y*global_dims[0])] <= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] ) || ( vertices_rem[4*(x+y*global_dims[0])] < vertices_loc[1] && vertices_loc[1] <= vertices_rem[4*(x+y*global_dims[0])+1] ) || - ( vertices_rem[4*(x+y*global_dims[0])] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] && + ( vertices_rem[4*(x+y*global_dims[0])] >= vertices_loc[0] && vertices_loc[0] < vertices_rem[4*(x+y*global_dims[0])+1] && vertices_loc[1] >= vertices_rem[4*(x+y*global_dims[0])+1] ) ) )