00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "FieldLayout/VnodeMultiBalancer.h"
00034 #include "FieldLayout/BinaryBalancer.h"
00035 #include "FieldLayout/FieldLayout.h"
00036 #include "Field/BareField.h"
00037 #include "Profile/Profiler.h"
00038
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00057
00058
00059 template<unsigned Dim>
00060 void VnodeMultiRepartition(FieldLayout<Dim>& layout,
00061 vector<BareField<bool,Dim>* >& weights) {
00062
00063 TAU_TYPE_STRING(taustr, " (" + CT(layout) + ", "+ CT(weights) + " )");
00064 TAU_PROFILE("VnodeMultiRepartition()", taustr, TAU_LAYOUT);
00065
00066 int npe = Ippl::Comm->getNodes();
00067 if (npe == 1) return;
00068
00069
00070
00071 unsigned vpd[Dim];
00072 int vnodes = 1;
00073 for (int d=0; d<Dim; d++) {
00074 vpd[d] = layout.getVnodesPerDirection(d);
00075 vnodes *= vpd[d];
00076 }
00077
00078
00079 NDIndex<Dim> vfndi;
00080 for (int d=0; d<Dim; d++) vfndi[d] = Index(vpd[d]);
00081
00082 e_dim_tag edt[Dim];
00083 for (int d=0; d<Dim; d++) edt[d] = layout.getDistribution(d);
00084
00085
00086
00087
00088
00089 FieldLayout<Dim> l(vfndi, edt, vpd, true, vnodes);
00090 BareField<double,Dim> vf(l);
00091 vf = 0.0;
00092
00093
00094
00095
00096
00097
00098
00099 int* anyTrueElements = new int[vnodes];
00100 for (int v=0; v < vnodes; v++) anyTrueElements[v] = 0;
00101
00102
00103 typename vector<BareField<bool,Dim>* >::iterator bfi;
00104 for (bfi = weights.begin(); bfi != weights.end(); ++bfi) {
00105 BareField<bool,Dim>& weight = *(*bfi);
00106 typename BareField<bool,Dim>::iterator_if weightItr;
00107
00108 for (weightItr = weight.begin_if();
00109 weightItr != weight.end_if();
00110 ++weightItr) {
00111 if ((*weightItr).second->IsCompressed()) {
00112 if ((*weightItr).second->getCompressedData()) {
00113 anyTrueElements[(*weightItr).second->getVnode()] += 1;
00114 }
00115 } else {
00116 anyTrueElements[(*weightItr).second->getVnode()] += 1;
00117 }
00118 }
00119 }
00120
00121
00122
00123
00124 int pe = Ippl::Comm->myNode();
00125 Message *msg;
00126 int partialTag = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00127 int completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00128 if (pe == 0) {
00129
00130 int* anyTrueElementsPartial = new int[vnodes];
00131 int notReceived = npe - 1;
00132 while (notReceived > 0) {
00133 int otherPE = COMM_ANY_NODE;
00134 int tag = partialTag;
00135 Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00136 msg2->get(anyTrueElementsPartial);
00137 delete msg2;
00138
00139 for (int v=0; v < vnodes; v++) {
00140
00141
00142
00143 if ((anyTrueElements[v] != 0) && (anyTrueElementsPartial[v] != 0)) {
00144 ERRORMSG("VnodeMultiRepartition(): anyTrueElements[" << v << "] = "
00145 << anyTrueElements[v] << " and anyTrueElementsPartial["
00146 << v << "] = " << anyTrueElementsPartial[v]
00147 << " ; inconsistent!" << endl);
00148 }
00149 anyTrueElements[v] += anyTrueElementsPartial[v];
00150 }
00151 notReceived--;
00152 }
00153 msg = new Message();
00154 msg->put(anyTrueElements, anyTrueElements + vnodes);
00155
00156 Ippl::Comm->broadcast_others(msg, completeTag);
00157 delete [] anyTrueElementsPartial;
00158 } else {
00159
00160 msg = new Message();
00161 msg->put(anyTrueElements, anyTrueElements + vnodes);
00162 Ippl::Comm->send(msg, 0, partialTag);
00163
00164 int pe0 = 0;
00165 msg = Ippl::Comm->receive_block(pe0, completeTag);
00166 msg->get(anyTrueElements);
00167 }
00168
00169
00170 typename BareField<double,Dim>::iterator_if vfItr;
00171 for (vfItr = vf.begin_if(); vfItr != vf.end_if(); ++vfItr) {
00172
00173
00174 int vnode = (*vfItr).second->getVnode();
00175
00176
00177
00178
00179
00180
00181
00182
00183 (*vfItr).second->Compress(anyTrueElements[vnode]);
00184
00185 }
00186
00187
00188
00189 BinaryRepartition(l, vf);
00190
00191
00192
00193
00194
00195
00196 int nZeroSizeVnodes = 0;
00197
00198 typename FieldLayout<Dim>::iterator_iv lLocals;
00199 for (lLocals = l.begin_iv(); lLocals != l.end_iv(); ++lLocals) {
00200 if ((*lLocals).second->getDomain().size() == 0) {nZeroSizeVnodes += 1;}
00201 }
00202
00203 typename FieldLayout<Dim>::iterator_dv lRemotes;
00204 for (lRemotes = l.begin_rdv(); lRemotes != l.end_rdv(); ++lRemotes) {
00205 if ((*lRemotes).second->getDomain().size() == 0) {nZeroSizeVnodes += 1;}
00206 }
00207
00208
00209
00210
00211
00212
00213 if (nZeroSizeVnodes != 0) {
00214 WARNMSG("VnodeMultiRepartition() was not able to get a successful "
00215 << "rebalance. So, it is leaving the FieldLayout vnode "
00216 << "PE-partioning the way it was whenyou called it. Sorry about "
00217 << "that; there just aren't enough noncompressed vnodes to go "
00218 << "around for this many PEs---at least not enough located in a "
00219 << "way that the underlying BinaryBalancer algorithm can deal "
00220 << "with." << endl);
00221
00222 delete [] anyTrueElements;
00223 return;
00224 }
00225
00226 #ifdef GROSS
00227
00228
00229
00230
00231 #endif // GROSS
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 int* peOwner = new int[vnodes];
00243
00244 for (int v=0; v < vnodes; v++) peOwner[v] = -1;
00245
00246
00247
00248
00249
00250 for (vfItr = vf.begin_if(); vfItr != vf.end_if(); ++vfItr) {
00251
00252
00253 typename LField<double,Dim>::iterator lfi;
00254 for (lfi = (*vfItr).second->begin();
00255 lfi != (*vfItr).second->end(); ++lfi) {
00256
00257 int vfIndex[Dim];
00258
00259
00260
00261 int lfBase[Dim];
00262 for (int d=0; d<Dim; d++) {
00263 lfBase[d] = (*vfItr).second->getOwned()[d].first();
00264 }
00265 for (int d=0; d<Dim; d++) vfIndex[d] = lfi.GetOffset(d) + lfBase[d];
00266
00267 int vnode = vfIndex[0];
00268 int multipplier = 1;
00269 for (int d=1; d<Dim; d++) {
00270 multipplier *= vpd[d-1];
00271 vnode += vfIndex[d]*multipplier;
00272 }
00273 if (vnode >= vnodes) {
00274 ERRORMSG("VnodeMultiRepartition(): vnode = " << vnode
00275 << " but vnodes is only " << vnodes << " ; inconsistent!"
00276 << endl);
00277 PInsist(vnode < vnodes,
00278 "VnodeMultiRepartition: exit because of vnode value error.");
00279 }
00280
00281
00282
00283
00284 peOwner[vnode] = pe;
00285 }
00286 }
00287
00288
00289
00290 partialTag = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00291 completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00292 Message* msg4;
00293 if (pe == 0) {
00294
00295 int* peOwnerPartial = new int[vnodes];
00296 int notReceived = npe - 1;
00297 while (notReceived > 0) {
00298 int otherPE = COMM_ANY_NODE;
00299 int tag = partialTag;
00300 Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00301 msg2->getmsg((void *)peOwnerPartial);
00302 delete msg2;
00303
00304 for (int v=0; v < vnodes; v++) {
00305 if (peOwnerPartial[v] != -1) {
00306
00307
00308
00309 if (peOwner[v] != -1) {
00310 ERRORMSG("VnodeMultiRepartition(): peOwner[" << v << "] = "
00311 << peOwner[v] << " and peOwnerPartial["
00312 << v << "] = " << peOwnerPartial[v]
00313 << " ; inconsistent!" << endl);
00314 }
00315 peOwner[v] = peOwnerPartial[v];
00316 }
00317 }
00318 notReceived--;
00319 }
00320 msg4 = new Message();
00321 msg4->put(peOwner, peOwner + vnodes);
00322
00323 Ippl::Comm->broadcast_others(msg4, completeTag);
00324 delete [] peOwnerPartial;
00325 } else {
00326
00327 msg4 = new Message();
00328 msg4->put(peOwner, peOwner + vnodes);
00329 Ippl::Comm->send(msg4, 0, partialTag);
00330
00331 int pe0 = 0;
00332 msg4 = Ippl::Comm->receive_block(pe0, completeTag);
00333 msg4->get(peOwner);
00334 }
00335 delete msg4;
00336
00337
00338
00339
00340
00341
00342 int nVnodesIOwn = 0;
00343 for (int v=0; v < vnodes; v++) if (peOwner[v] == pe) ++nVnodesIOwn;
00344
00345
00346 Vnode<Dim>* domains = new Vnode<Dim>[nVnodesIOwn];
00347
00348
00349
00350
00351 typename FieldLayout<Dim>::iterator_iv oldLocals;
00352 int domain = 0;
00353 for (oldLocals = layout.begin_iv(); oldLocals != layout.end_iv();
00354 ++oldLocals) {
00355
00356 int vnode = (*oldLocals).second->getVnode();
00357 if (peOwner[vnode] == pe) {
00358 domains[domain] =
00359 Vnode<Dim>((*oldLocals).second->getDomain(), pe, vnode);
00360 ++domain;
00361 }
00362 }
00363
00364
00365 typename FieldLayout<Dim>::iterator_dv oldRemotes;
00366 for (oldRemotes = layout.begin_rdv(); oldRemotes != layout.end_rdv();
00367 ++oldRemotes) {
00368
00369 int vnode = (*oldRemotes).second->getVnode();
00370 if (peOwner[vnode] == pe) {
00371 domains[domain] =
00372 Vnode<Dim>((*oldRemotes).second->getDomain(), pe, vnode);
00373 ++domain;
00374 }
00375 }
00376
00377
00378
00379 layout.Repartition(domains, domains + nVnodesIOwn);
00380
00381
00382
00383 delete [] anyTrueElements;
00384 delete [] peOwner;
00385 delete [] domains;
00386
00387 return;
00388 }
00389
00390 #ifdef GROSS
00391
00392
00393
00394
00395
00396 FieldLayout<Dim> l2(vfndi, edt, vpd, true, vnodes);
00397 if (nZeroSizeVnodes != 0) {
00398
00399
00400
00401
00402
00403
00404 BareField<double,Dim> vf2(l2);
00405 vf2 = 0.0;
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 for (int v=0; v < vnodes; v++) anyTrueElements[v] = 0;
00416
00417
00418 vector<BareField<bool,Dim>* >::iterator bfi2;
00419 for (bfi2 = weights.begin(); bfi2 != weights.end(); ++bfi2) {
00420 BareField<bool,Dim>& weight2 = *(*bfi2);
00421 BareField<bool,Dim>::iterator_if weight2Itr;
00422
00423 for (weight2Itr = weight2.begin_if();
00424 weight2Itr != weight2.end_if();
00425 ++weight2Itr) {
00426 if ((*weight2Itr).second->IsCompressed()) {
00427 if ((*weight2Itr).second->getCompressedData()) {
00428 anyTrueElements[(*weight2Itr).second->getVnode()] += 1;
00429 }
00430 } else {
00431 anyTrueElements[(*weight2Itr).second->getVnode()] += 1;
00432 }
00433 }
00434 }
00435
00436
00437
00438 double normfact = sum(Abs(vf2));
00439 normfact = normfact/vfndi.size();
00440 double epsilon = 1.0/normfact;
00441 vf2 += epsilon*IpplRandom;
00442
00443
00444
00445
00446
00447
00448
00449 partialTag = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00450 completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00451 Message *msg3;
00452 if (pe == 0) {
00453
00454 int* anyTrueElementsPartial = new int[vnodes];
00455 int notReceived = npe - 1;
00456 while (notReceived > 0) {
00457 int otherPE = COMM_ANY_NODE;
00458 int tag = partialTag;
00459 Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00460 msg2->get(anyTrueElementsPartial);
00461 delete msg2;
00462
00463 for (int v=0; v < vnodes; v++) {
00464
00465
00466
00467 if ((anyTrueElements[v] != 0) && (anyTrueElementsPartial[v] != 0)) {
00468 ERRORMSG("VnodeMultiRepartition(): anyTrueElements[" << v << "] = "
00469 << anyTrueElements[v] << " and anyTrueElementsPartial["
00470 << v << "] = " << anyTrueElementsPartial[v]
00471 << " ; inconsistent!" << endl);
00472 }
00473 anyTrueElements[v] += anyTrueElementsPartial[v];
00474 }
00475 notReceived--;
00476 }
00477 msg3 = new Message();
00478 msg3->put(anyTrueElements, anyTrueElements + vnodes);
00479
00480 Ippl::Comm->broadcast_others(msg3, completeTag);
00481 delete [] anyTrueElementsPartial;
00482 } else {
00483
00484 msg3 = new Message();
00485 msg3->put(anyTrueElements, anyTrueElements + vnodes);
00486 Ippl::Comm->send(msg3, 0, partialTag);
00487
00488 int pe0 = 0;
00489 msg3 = Ippl::Comm->receive_block(pe0, completeTag);
00490 msg3->get(anyTrueElements);
00491 }
00492 delete msg3;
00493
00494
00495 BareField<double,Dim>::iterator_if vf2Itr;
00496 for (vf2Itr = vf2.begin_if(); vf2Itr != vf2.end_if(); ++vf2Itr) {
00497
00498
00499 int vnode = (*vf2Itr).second->getVnode();
00500
00501
00502
00503
00504
00505
00506
00507
00508 (*vf2Itr).second->Compress(anyTrueElements[vnode]);
00509
00510 }
00511
00512
00513 BinaryRepartition(l2, vf2);
00514
00515
00516
00517
00518
00519
00520
00521 int nZeroSizeVnodes2 = 0;
00522
00523 FieldLayout<Dim>::iterator_iv l2Locals;
00524 for (l2Locals = l2.begin_iv(); l2Locals != l2.end_iv(); ++l2Locals) {
00525 if ((*l2Locals).second->getDomain().size() == 0) {nZeroSizeVnodes2 += 1;}
00526 }
00527
00528 FieldLayout<Dim>::iterator_dv l2Remotes;
00529 for (l2Remotes = l2.begin_rdv(); l2Remotes != l2.end_rdv(); ++l2Remotes) {
00530 if ((*l2Remotes).second->getDomain().size() == 0) {nZeroSizeVnodes2 += 1;}
00531 }
00532
00533
00534
00535 if (nZeroSizeVnodes2 != 0) {
00536 WARNMSG("VnodeMultiRepartition(): even on a desperate 2nd attempt by adding in some"
00537 << "random nonzero vnodes, was not able to get a successful rebalance. So, "
00538 << "leaving the FieldLayout partioning the way it was when you called"
00539 << " VnodeMultiRepartition(). Sorry about that." << endl);
00540 return;
00541 } else {
00542
00543
00544 l = l2;
00545 l2.Repartition
00546 vf = vf2;
00547 }
00548 }
00549 #endif // GROSS
00550
00551
00552
00553
00554
00555