OpenLB 1.7
Loading...
Searching...
No Matches
heuristicLoadBalancer.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012 Jonas Fietz, Mathias J. Krause
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef HEURISTIC_LOAD_BALANCER_HH
25#define HEURISTIC_LOAD_BALANCER_HH
26
27#include <algorithm>
28#include <vector>
29#include <map>
30#include <math.h>
31#include "core/cell.h"
32#include "core/util.h"
34#include "geometry/cuboid3D.h"
37
38namespace olb {
39
40template <typename T> class Cuboid2D;
41template <typename T> class Cuboid3D;
42
43template<typename T>
45 const double ratioFullEmpty, const double weightEmpty)
46 : _ratioFullEmpty(ratioFullEmpty)
47{
48 reInit(cGeometry3d, ratioFullEmpty, weightEmpty);
49}
50
51template<typename T>
53 const double ratioFullEmpty, const double weightEmpty)
54 : _ratioFullEmpty(ratioFullEmpty)
55{
56 reInit(cGeometry2d, ratioFullEmpty, weightEmpty);
57}
58
59template<typename T>
63
64template<typename T>
66{
67 LoadBalancer<T>::swap(loadBalancer);
68
69#ifdef PARALLEL_MODE_MPI
70 _mpiNbHelper.swap(loadBalancer._mpiNbHelper);
71#endif
72
73 std::swap(_cGeometry3d, loadBalancer._cGeometry3d);
74 std::swap(_cGeometry2d, loadBalancer._cGeometry2d);
75}
76
77template<typename T>
78void HeuristicLoadBalancer<T>::reInit(CuboidGeometry3D<T>& cGeometry3d, const double ratioFullEmpty, const double weightEmpty)
79{
80 _ratioFullEmpty = ratioFullEmpty;
81 this->_glob.clear();
82 _cGeometry3d = &cGeometry3d;
83 int rank = 0;
84 int size = 1;
85 int nC = _cGeometry3d->getNc();
86#ifdef PARALLEL_MODE_MPI
87 rank = singleton::mpi().getRank();
88 size = util::max<int>(singleton::mpi().getSize(), 1);
89#endif
90 //int xN, yN, zN;
91 //T globX, globY, globZ;//, delta;
92 //boost::shared_array<int> tempInCN(new int[nC]);
93
94 std::vector<int> cuboidToThread(nC);
95 std::vector<int> partitionResult(nC);
96 std::vector<int> vwgt(nC); // node weights
97 std::vector<int> taken(nC, 0);
98 std::vector<int> currentLoad(size, 0);
99
100 if (size == 1) {
101 for (int i = 0; i < nC; ++i) {
102 this->_glob.push_back(i);
103 this->_loc[i] = i;
104 this->_rank[i] = 0;
105 };
106 this->_size = nC;
107 return;
108 }
109
110 if (rank == 0) {
111 for ( int iC = 0; iC < nC; iC++) { // assemble neighbourhood information
112
113 int fullCells = _cGeometry3d->get(iC).getWeight();
114 vwgt[iC] = int(weightEmpty*(_cGeometry3d->get(iC).getLatticeVolume() - fullCells)) + int(ratioFullEmpty * fullCells);
115 }
116
117 int maxLoad = -1;
118 int maxIC = -1;
119 do {
120 maxLoad = -1;
121 maxIC = -1;
122 for ( int iC = 0 ; iC < nC; iC++) {
123 if (taken[iC] == 0 && vwgt[iC] > maxLoad) {
124 maxLoad = vwgt[iC];
125 maxIC = iC;
126 }
127 }
128
129 if (maxIC != -1) {
130 double minLoad = currentLoad[0];
131 int minJ = 0;
132 for (int j = 1; j < size; j++) {
133 if (currentLoad[j] < minLoad) {
134 minLoad = currentLoad[j];
135 minJ = j;
136 }
137 }
138 taken[maxIC] = 1;
139 currentLoad[minJ] += maxLoad;
140 partitionResult[maxIC] = minJ;
141 }
142 }
143 while (maxLoad != -1);
144#if 0
145 std::cout << "vwgt" << std::endl;
146 for (int i = 0; i < nC; i++) {
147 std::cout << "[" << i << "]="<< vwgt[i] << std::endl;
148 }
149
150 for (int i = 0; i < size; i++) {
151 std::cout << "load[" << i << "]=" << currentLoad[i] << std::endl;
152 }
153
154 std::cout << "vwgt" << std::endl;
155 for (int i = 0; i < nC; i++) {
156 std::cout << vwgt[i] << std::endl;
157 }
158 std::cout << "xadj" << std::endl;
159 for (int i = 0; i < nC+1; i++) {
160 std::cout << xadj[i] << std::endl;
161 }
162 std::cout << "adjncy" << std::endl;
163 for (int i = 0; i <adjncy.size(); i++) {
164 std::cout << adjncy[i] << std::endl;
165 }
166 std::cout << "adjcwgt" << std::endl;
167 for (int i = 0; i < adjcwgt.size(); i++) {
168 std::cout << adjcwgt[i] << std::endl;
169 }
170
171 std::cout << "nC" << nC << " size " << size << " inbalance " <<
172 inbalance << std::endl;
173#endif
174 int count = 0;
175 for (int i = 0; i < nC; ++i) {
176 if (partitionResult[i] == 0) {
177 this->_glob.push_back(i);
178 this->_loc[i] = count;
179 count++;
180 };
181 this->_rank[i] = partitionResult[i];
182 cuboidToThread[i] = partitionResult[i];
183 }
184 this->_size = count;
185 }
186 // Send all threads their number of cuboids
187
188#ifdef PARALLEL_MODE_MPI
189 if (rank == 0) {
190 // Send all threads their respective cuboids
191 _mpiNbHelper.free();
192 _mpiNbHelper.allocate(size-1);
193 for (int i = 1; i < size; i++) {
194 singleton::mpi().iSend(&cuboidToThread.front(),
195 nC, i, &_mpiNbHelper.get_mpiRequest()[i-1], 0);
196 }
197 singleton::mpi().waitAll(_mpiNbHelper);
198 }
199 else {
200 int *tmpCuboids = new int[nC];
201 singleton::mpi().receive(tmpCuboids, nC, 0, 0);
202 int count = 0;
203 for (int i = 0; i < nC; ++i) {
204 if (tmpCuboids[i] == rank) {
205 this->_glob.push_back(i);
206 this->_loc[i] = count;
207 count++;
208 };
209 this->_rank[i] = tmpCuboids[i];
210 }
211 delete[] tmpCuboids;
212 this->_size = count;
213 }
214#endif
215#ifdef OLB_DEBUG
216 this->print();
217#endif
218}
219
220template<typename T>
221void HeuristicLoadBalancer<T>::reInit(CuboidGeometry2D<T>& cGeometry2d, const double ratioFullEmpty, const double weightEmpty)
222{
223 _ratioFullEmpty = ratioFullEmpty;
224 this->_glob.clear();
225 _cGeometry2d = &cGeometry2d;
226 int rank = 0;
227 int size = 1;
228 int nC = _cGeometry2d->getNc();
229#ifdef PARALLEL_MODE_MPI
230 rank = singleton::mpi().getRank();
231 size = util::max<int>(singleton::mpi().getSize(), 1);
232#endif
233 //int xN, yN;
234 //T globX, globY;//, delta;
235 //boost::shared_array<int> tempInCN(new int[nC]);
236
237 std::vector<int> cuboidToThread(nC);
238 std::vector<int> partitionResult(nC);
239 std::vector<int> vwgt(nC); // node weights
240 std::vector<int> taken(nC, 0);
241 std::vector<int> currentLoad(size, 0);
242
243 if (size == 1) {
244 for (int i = 0; i < nC; ++i) {
245 this->_glob.push_back(i);
246 this->_loc[i] = i;
247 this->_rank[i] = 0;
248 };
249 this->_size = nC;
250 return;
251 }
252
253 if (rank == 0) {
254 for ( int iC = 0; iC < nC; iC++) { // assemble neighbourhood information
255
256 int fullCells = _cGeometry2d->get(iC).getWeight();
257 vwgt[iC] = int(weightEmpty*(_cGeometry2d->get(iC).getLatticeVolume() - fullCells)) + int(ratioFullEmpty * fullCells);
258
259 }
260
261 int maxLoad = -1;
262 int maxIC = -1;
263 do {
264 maxLoad = -1;
265 maxIC = -1;
266 for ( int iC = 0 ; iC < nC; iC++) {
267 if (taken[iC] == 0 && vwgt[iC] > maxLoad) {
268 maxLoad = vwgt[iC];
269 maxIC = iC;
270 }
271 }
272
273 if (maxIC != -1) {
274 double minLoad = currentLoad[0];
275 int minJ = 0;
276 for (int j = 1; j < size; j++) {
277 if (currentLoad[j] < minLoad) {
278 minLoad = currentLoad[j];
279 minJ = j;
280 }
281 }
282 taken[maxIC] = 1;
283 currentLoad[minJ] += maxLoad;
284 partitionResult[maxIC] = minJ;
285 }
286 }
287 while (maxLoad != -1);
288#if 0
289 std::cout << "vwgt" << std::endl;
290 for (int i = 0; i < nC; i++) {
291 std::cout << "[" << i << "]="<< vwgt[i] << std::endl;
292 }
293
294 for (int i = 0; i < size; i++) {
295 std::cout << "load[" << i << "]=" << currentLoad[i] << std::endl;
296 }
297
298 std::cout << "vwgt" << std::endl;
299 for (int i = 0; i < nC; i++) {
300 std::cout << vwgt[i] << std::endl;
301 }
302 std::cout << "xadj" << std::endl;
303 for (int i = 0; i < nC+1; i++) {
304 std::cout << xadj[i] << std::endl;
305 }
306 std::cout << "adjncy" << std::endl;
307 for (int i = 0; i <adjncy.size(); i++) {
308 std::cout << adjncy[i] << std::endl;
309 }
310 std::cout << "adjcwgt" << std::endl;
311 for (int i = 0; i < adjcwgt.size(); i++) {
312 std::cout << adjcwgt[i] << std::endl;
313 }
314
315 std::cout << "nC" << nC << " size " << size << " inbalance " <<
316 inbalance << std::endl;
317#endif
318 int count = 0;
319 for (int i = 0; i < nC; ++i) {
320 if (partitionResult[i] == 0) {
321 this->_glob.push_back(i);
322 this->_loc[i] = count;
323 count++;
324 };
325 this->_rank[i] = partitionResult[i];
326 cuboidToThread[i] = partitionResult[i];
327 }
328 this->_size = count;
329 }
330 // Send all threads their number of cuboids
331
332#ifdef PARALLEL_MODE_MPI
333 if (rank == 0) {
334 // Send all threads their respective cuboids
335 _mpiNbHelper.free();
336 _mpiNbHelper.allocate(size-1);
337 for (int i = 1; i < size; i++) {
338 singleton::mpi().iSend(&cuboidToThread.front(),
339 nC, i, &_mpiNbHelper.get_mpiRequest()[i-1], 0);
340 }
341 singleton::mpi().waitAll(_mpiNbHelper);
342 }
343 else {
344 int *tmpCuboids = new int[nC];
345 singleton::mpi().receive(tmpCuboids, nC, 0, 0);
346 int count = 0;
347 for (int i = 0; i < nC; ++i) {
348 if (tmpCuboids[i] == rank) {
349 this->_glob.push_back(i);
350 this->_loc[i] = count;
351 count++;
352 };
353 this->_rank[i] = tmpCuboids[i];
354 }
355 delete[] tmpCuboids;
356 this->_size = count;
357 }
358#endif
359#ifdef OLB_DEBUG
360 this->print();
361#endif
362}
363
364
365} // namespace olb
366#endif
Definition of a LB cell – header file.
A cuboid structure represents the grid of a considered domain.
int getNc() const
Returns the number of cuboids in t < 2he structure.
A cuboid geometry represents a voxel mesh.
int getNc() const
Returns the number of cuboids in the structure.
Constructs a load balancer from a given cuboid geometry using a heurist.
void swap(HeuristicLoadBalancer< T > &loadBalancer)
void reInit(CuboidGeometry3D< T > &cGeometry3d, const double ratioFullEmpty=1., const double weightEmpty=.0)
void swap(LoadBalancer< T > &loadBalancer)
Swap method.
void iSend(T *buf, int count, int dest, MPI_Request *request, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Sends data at *buf, non blocking.
int getRank() const
Returns the process ID.
void waitAll(MpiNonBlockingHelper &mpiNbHelper)
Complete a series of non-blocking MPI operations.
void receive(T *buf, int count, int source, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Receives data at *buf, blocking.
The description of a single 3D cuboid – header file.
The description of a vector of 2D cuboid – header file.
The description of a vector of 3D cuboid – header file.
MpiManager & mpi()
Top level namespace for all of OpenLB.
Set of functions commonly used in LB computations – header file.