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
00027
00028
00029
00030
00031
00032
00033
00035
00036
00037 #include "Field/Assign.h"
00038 #include "Field/AssignDefs.h"
00039 #include "Field/BareField.h"
00040 #include "Field/BrickExpression.h"
00041 #include "Field/IndexedBareField.h"
00042 #include "Field/LField.h"
00043 #include "Message/Communicate.h"
00044 #include "Message/Message.h"
00045 #include "Utility/PAssert.h"
00046 #include "Utility/IpplInfo.h"
00047 #include "Utility/IpplStats.h"
00048 #include "Profile/Profiler.h"
00049 #include "PETE/IpplExpressions.h"
00050
00051 #ifdef IPPL_STDSTL
00052 #include <map>
00053 #include <vector>
00054 #include <functional>
00055 #include <utility>
00056 using namespace std;
00057 #else
00058 #include <map.h>
00059 #include <vector.h>
00060 #include <function.h>
00061 #include <multimap.h>
00062 #endif
00063
00064 #ifdef IPPL_USE_STANDARD_HEADERS
00065 #include <iostream>
00066 #include <typeinfo>
00067 using namespace std;
00068 #else
00069 #include <iostream.h>
00070 #include <typeinfo.h>
00071 #endif
00072
00073
00075
00076
00077
00079
00080 template<class T1, class T2, unsigned D1, unsigned D2>
00081 inline void
00082 IndexedSend(IndexedBareField<T1,D1,D1>& ilhs,
00083 IndexedBareField<T2,D2,D2>& irhs,
00084 int tag)
00085 {
00086 TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", int)" );
00087 TAU_PROFILE("IndexedSend()", taustr, TAU_FIELD);
00088
00089
00090
00091 ASSIGNMSG(Inform msg("IndexedSend", INFORM_ALL_NODES));
00092 ASSIGNMSG(msg << "Sending out messages for IBF[" << ilhs.getDomain());
00093 ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00094
00095
00096 BareField<T1,D1> &lhs = ilhs.getBareField();
00097 BareField<T2,D2> &rhs = irhs.getBareField();
00098 typename BareField<T2,D2>::iterator_if rf_i, rf_e = rhs.end_if();
00099 T2 compressed_value;
00100
00101
00102 int nprocs = Ippl::getNodes();
00103 Message** mess = new Message*[nprocs];
00104 int iproc;
00105 for (iproc=0; iproc<nprocs; ++iproc)
00106 mess[iproc] = 0;
00107
00108
00109
00110 for (rf_i = rhs.begin_if(); rf_i != rf_e; ++rf_i) {
00111
00112 LField<T2,D2> &rf = *((*rf_i).second);
00113 const NDIndex<D2>& ro = rf.getOwned();
00114
00115
00116 if ( ro.touches( irhs.getDomain() ) ) {
00117
00118 NDIndex<D2> rt = irhs.getDomain().intersect( ro );
00119
00120
00121 NDIndex<D1> lt = ilhs.getDomain().plugBase( rt );
00122
00123
00124 typename FieldLayout<D1>::touch_range_dv
00125 range(lhs.getLayout().touch_range_rdv(lt,lhs.getGuardCellSizes()));
00126 typename FieldLayout<D1>::touch_iterator_dv remote_i;
00127 for (remote_i = range.first; remote_i != range.second; ++remote_i) {
00128
00129 NDIndex<D1> left_intersect = lt.intersect( (*remote_i).first );
00130
00131
00132 int rnode = (*remote_i).second->getNode();
00133
00134
00135 NDIndex<D2> right_intersect =
00136 irhs.getDomain().plugBase(left_intersect);
00137
00138
00139 typename LField<T2,D2>::iterator rhs_i =
00140 rf.begin(right_intersect, compressed_value);
00141
00142 ASSIGNMSG(msg << "Sending IndexedField data from domain ");
00143 ASSIGNMSG(msg << right_intersect << " to domain " << left_intersect);
00144 ASSIGNMSG(msg << endl);
00145
00146
00147 CompressedBrickIterator<T2,D1> prhs_i =
00148 rhs_i.permute(right_intersect,left_intersect);
00149
00150
00151 prhs_i.TryCompress();
00152
00153
00154 if (!mess[rnode]) mess[rnode] = new Message;
00155 PAssert(mess[rnode]);
00156 left_intersect.putMessage(*mess[rnode]);
00157 prhs_i.putMessage(*mess[rnode]);
00158 }
00159 }
00160 }
00161
00162
00163 for (iproc=0; iproc<nprocs; ++iproc) {
00164 if (mess[iproc])
00165 Ippl::Comm->send(mess[iproc],iproc,tag);
00166 }
00167
00168 delete [] mess;
00169 return;
00170 }
00171
00172
00174
00175
00176
00178
00179 template<class T1, class T2, unsigned D1, unsigned D2, class Container>
00180 inline void
00181 CalcIndexedReceive(IndexedBareField<T1,D1,D1>& ilhs,
00182 IndexedBareField<T2,D2,D2>& irhs,
00183 Container& recv_ac, int& msgnum)
00184 {
00185 TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00186 CT(recv_ac) + " )" );
00187 TAU_PROFILE("CalcIndexedReceive()", taustr, TAU_FIELD);
00188
00189
00190
00191 ASSIGNMSG(Inform msg("CalcIndexedReceive", INFORM_ALL_NODES));
00192 ASSIGNMSG(msg << "Computing receive messages for IBF[" << ilhs.getDomain());
00193 ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00194
00195
00196 BareField<T1,D1> &lhs = ilhs.getBareField();
00197 BareField<T2,D2> &rhs = irhs.getBareField();
00198 typename BareField<T1,D1>::iterator_if lf_i, lf_e = lhs.end_if();
00199
00200 int nprocs = Ippl::getNodes();
00201 bool* recvmsg = new bool[nprocs];
00202 int iproc;
00203 for (iproc=0; iproc<nprocs; ++iproc)
00204 recvmsg[iproc] = false;
00205
00206
00207 for (lf_i = lhs.begin_if(); lf_i != lf_e; ++lf_i) {
00208
00209 LField<T1,D1> &lf = *((*lf_i).second);
00210 const NDIndex<D1>& la = lf.getAllocated();
00211
00212 if ( la.touches( ilhs.getDomain() ) ) {
00213
00214 NDIndex<D1> lt = ilhs.getDomain().intersect( la );
00215
00216 NDIndex<D2> rt = irhs.getDomain().plugBase( lt );
00217
00218 typename FieldLayout<D2>::touch_range_dv
00219 range( rhs.getLayout().touch_range_rdv(rt) );
00220
00221 typename FieldLayout<D2>::touch_iterator_dv rv_i;
00222 for (rv_i = range.first; rv_i != range.second; ++rv_i) {
00223
00224 NDIndex<D2> ri = rt.intersect((*rv_i).first);
00225 NDIndex<D1> li = ilhs.getDomain().plugBase( ri );
00226
00227 ASSIGNMSG(msg << "Expecting IndexedField data from domain " << ri);
00228 ASSIGNMSG(msg << " for domain " << li << endl);
00229
00230 typedef typename Container::value_type value_type;
00231 recv_ac.insert(value_type(li,&lf));
00232
00233 int rnode = (*rv_i).second->getNode();
00234 recvmsg[rnode] = true;
00235 }
00236 }
00237 }
00238
00239 msgnum = 0;
00240 for (iproc=0; iproc<nprocs; ++iproc)
00241 if (recvmsg[iproc]) ++msgnum;
00242 delete [] recvmsg;
00243 return;
00244 }
00245
00246
00248
00249
00250
00252
00253 template<class T1, class T2, unsigned D1, unsigned D2, class Op>
00254 inline void
00255 IndexedLocalAssign(IndexedBareField<T1,D1,D1>& ilhs,
00256 IndexedBareField<T2,D2,D2>& irhs,
00257 Op& op)
00258 {
00259 TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00260 CT(op) + " )" );
00261 TAU_PROFILE("IndexedLocalAssign()", taustr, TAU_FIELD);
00262
00263
00264
00265 ASSIGNMSG(Inform msg("IndexedLocalAssign-IBF", INFORM_ALL_NODES));
00266 ASSIGNMSG(msg << "Computing general local assignment to IBF[");
00267 ASSIGNMSG(msg << ilhs.getDomain() << "] = IBF[");
00268 ASSIGNMSG(msg << irhs.getDomain() << "] ..." << endl);
00269
00270
00271 BareField<T1,D1> &lhs = ilhs.getBareField();
00272 BareField<T2,D2> &rhs = irhs.getBareField();
00273
00274
00275
00276
00277
00278 for (typename BareField<T1,D1>::iterator_if lf_i=lhs.begin_if();
00279 lf_i!=lhs.end_if(); ++lf_i)
00280 {
00281
00282 LField<T1,D1> &lf = *(*lf_i).second;
00283 const NDIndex<D1>& lo = lf.getOwned();
00284 const NDIndex<D1>& la = lf.getAllocated();
00285
00286
00287 if ( lo.touches( ilhs.getDomain() ) )
00288 {
00289 ASSIGNMSG(msg << "----------------" << endl);
00290 ASSIGNMSG(msg << "Assigning to local LField with owned = " << lo);
00291 ASSIGNMSG(msg << endl);
00292
00293
00294 NDIndex<D1> lt = ilhs.getDomain().intersect( lo );
00295 ASSIGNMSG(msg << "Intersection lhs domain = " << lt << endl);
00296
00297
00298 NDIndex<D2> rp = irhs.getDomain().plugBase( lt );
00299 ASSIGNMSG(msg << "Plugbase domain = " << rp << endl);
00300
00301
00302 for (typename BareField<T2,D2>::iterator_if rf_i = rhs.begin_if();
00303 rf_i != rhs.end_if(); ++rf_i)
00304 {
00305
00306 LField<T2,D2> &rf = *(*rf_i).second;
00307 const NDIndex<D2>& ra = rf.getAllocated();
00308 const NDIndex<D2>& ro = rf.getOwned();
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 const NDIndex<D2> &rd = ( ra.contains(rp) ? ra : ro );
00324 if ( rd.touches( rp ) )
00325 {
00326
00327 NDIndex<D2> rhsDomain = rp.intersect(rd);
00328
00329
00330 NDIndex<D1> lhsDomain = lt.plugBase(rhsDomain);
00331
00332 ASSIGNMSG(msg << "Found touching rhs field: assigning ");
00333 ASSIGNMSG(msg << lhsDomain << " = " << rhsDomain << endl);
00334
00335
00336 bool c1 = rf.IsCompressed();
00337
00338
00339
00340 bool c2 = lhsDomain.containsAllPoints(la);
00341 bool c3 = OperatorTraits<Op>::IsAssign;
00342 bool c4 = lf.IsCompressed();
00343 ASSIGNMSG(msg << "Checking for possible compressed-assign:");
00344 ASSIGNMSG(msg << "\n rf.IsCompressed = " << c1);
00345 ASSIGNMSG(msg << "\n lhs.contains(allocatd) = " << c2);
00346 ASSIGNMSG(msg << "\n lf.IsCompressed = " << c4);
00347 ASSIGNMSG(msg << "\n Doing assignment = " << c3);
00348 ASSIGNMSG(msg << "\n Result = " << (c1&&c2&&(c3||c4)));
00349 ASSIGNMSG(msg << endl);
00350 if ( lhs.compressible() && c1 && c2 && ( c3 || c4 ) )
00351 {
00352 ASSIGNMSG(msg << "Can do compressed assign from rhs ");
00353 ASSIGNMSG(msg << "to lhs." << endl);
00354
00355
00356 lf.Compress();
00357
00358
00359 PETE_apply(op, *lf.begin() , *rf.begin() );
00360 ASSIGNMSG(msg << "After compress, " << *lf.begin());
00361 ASSIGNMSG(msg << " = ");
00362 ASSIGNMSG(msg << *rf.begin() << endl);
00363 }
00364 else
00365 {
00366
00367
00368 bool c2 = lhsDomain.containsAllPoints(lo);
00369 bool c3 = OperatorTraits<Op>::IsAssign;
00370 bool filldom = ((!c2) || (!c3));
00371 ASSIGNMSG(msg << "Must uncompress, filldom = ");
00372 ASSIGNMSG(msg << filldom << endl);
00373 lf.Uncompress(filldom);
00374
00375
00376 typedef typename LField<T1,D1>::iterator LFI;
00377 typedef typename LField<T2,D1>::iterator RFI;
00378 typedef BrickExpression<D1,LFI,RFI,Op> Expr;
00379
00380
00381 RFI rhs_i =
00382 rf.begin(rhsDomain).permute(rhsDomain,lhsDomain) ;
00383 LFI lhs_i =
00384 lf.begin(lhsDomain) ;
00385
00386
00387 ASSIGNMSG(msg << "Doing full loop assignment." << endl);
00388 Expr(lhs_i,rhs_i,op).apply();
00389 }
00390 }
00391 }
00392 }
00393 }
00394 }
00395
00396
00398
00399
00400
00401
00403
00404 template<class T1, class T2, unsigned D1, unsigned D2,
00405 class Op, class Container>
00406 inline void
00407 IndexedReceive(IndexedBareField<T1,D1,D1>& ilhs,
00408 IndexedBareField<T2,D2,D2>& irhs,
00409 Op& op,
00410 Container& recv_ac, int msgnum,
00411 int tag)
00412 {
00413 TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00414 CT(op) + ", " + CT(recv_ac) + ", int )" );
00415 TAU_PROFILE("IndexedReceive()", taustr, TAU_FIELD);
00416
00417
00418
00419 ASSIGNMSG(Inform msg("IndexedReceive", INFORM_ALL_NODES));
00420 ASSIGNMSG(msg << "Receiving messages for IBF[" << ilhs.getDomain());
00421 ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00422
00423
00424 BareField<T1,D1> &lhs = ilhs.getBareField();
00425
00426
00427 typedef typename LField<T1,D1>::iterator LFI;
00428 typedef CompressedBrickIterator<T2,D1> RFI;
00429
00430
00431 typedef BrickExpression<D1,LFI,RFI,Op> Expr;
00432
00433
00434 while (msgnum>0) {
00435
00436 int any_node = COMM_ANY_NODE;
00437 Message *mess = Ippl::Comm->receive_block(any_node,tag);
00438 PAssert(mess != 0);
00439 --msgnum;
00440
00441 int ndoms = mess->size() / (D1 + 3);
00442 for (int idom=0; idom<ndoms; ++idom) {
00443
00444 NDIndex<D1> domain;
00445 domain.getMessage(*mess);
00446
00447 T2 compressed_data;
00448 RFI rhs_i(compressed_data);
00449 rhs_i.getMessage(*mess);
00450
00451 ASSIGNMSG(msg << "Received IndexedField data for domain " << domain);
00452 ASSIGNMSG(msg << endl);
00453
00454
00455 typename Container::iterator hit = recv_ac.find( domain );
00456 PAssert( hit != recv_ac.end() );
00457 LField<T1,D1> &lf = *(*hit).second;
00458
00459
00460 bool c1 = rhs_i.IsCompressed();
00461 bool c2 = domain.containsAllPoints( lf.getAllocated() );
00462 bool c3 = OperatorTraits<Op>::IsAssign;
00463 bool c4 = lf.IsCompressed();
00464 if ( lhs.compressible() && c1 && c2 && ( c3 || c4 ) ) {
00465
00466 lf.Compress();
00467
00468 PETE_apply(op, *lf.begin() , *rhs_i);
00469 }
00470 else {
00471
00472
00473 bool c2 = domain.containsAllPoints(lf.getOwned());
00474 bool c3 = OperatorTraits<Op>::IsAssign;
00475 lf.Uncompress( !(c2&&c3) );
00476
00477 LFI lhs_i = lf.begin(domain);
00478
00479 Expr(lhs_i,rhs_i,op).apply();
00480 }
00481
00482
00483 recv_ac.erase( hit );
00484 }
00485 delete mess;
00486 }
00487 return;
00488 }
00489
00490
00492
00493
00494
00495
00496
00498
00499 template<unsigned int D1, unsigned int D2>
00500 struct AssignTouches
00501 {
00502 static bool apply(const NDIndex<D1>&, const NDIndex<D2>&)
00503 {
00504 return false;
00505 }
00506 };
00507
00508 template<unsigned int D1>
00509 struct AssignTouches< D1, D1 >
00510 {
00511 static bool apply(const NDIndex<D1>& x,const NDIndex<D1>& y)
00512 {
00513 return x.touches(y);
00514 }
00515 };
00516
00517
00519
00520
00521
00522
00524
00525 template<class T1, unsigned D1, class RHS, class Op>
00526 void
00527 assign(IndexedBareField<T1,D1,D1> lhs,
00528 RHS rhsp,
00529 Op op, ExprTag<false>)
00530 {
00531
00532
00533
00534 TAU_TYPE_STRING(p1, "void (" + CT(lhs) + ", " + CT(rhsp) + ", " + CT(op)
00535 + ", ExprTag<false> )" );
00536 TAU_PROFILE("assign()", p1.data(), TAU_ASSIGN | TAU_FIELD);
00537 TAU_PROFILE_TIMER(sendtimer, " assign[IndexedBareField]-send",
00538 p1.data(), TAU_ASSIGN);
00539 TAU_PROFILE_TIMER(findtimer, " assign[IndexedBareField]-findreceive",
00540 p1.data(),TAU_ASSIGN);
00541 TAU_PROFILE_TIMER(localstimer, " assign[IndexedBareField]-locals",
00542 p1.data(), TAU_ASSIGN);
00543 TAU_PROFILE_TIMER(rectimer, " assign[IndexedBareField]-recieve",
00544 p1.data(), TAU_ASSIGN);
00545 TAU_PROFILE_TIMER(filltimer, " assign[IndexedBareField]-fill",
00546 p1.data(), TAU_ASSIGN);
00547
00548 typedef typename RHS::PETE_Return_t T2;
00549 enum { D2=RHS::Dim_u };
00550 IndexedBareField<T2,D2,D2> rhs ( rhsp.getBareField()[ rhsp.getDomain() ] );
00551
00552
00553
00554 if ( lhs.getBareField().get_Id() == rhs.getBareField().get_Id() )
00555 {
00556
00557 if ( AssignTouches<D1,D2>::apply(lhs.getDomain(),rhs.getDomain()))
00558 {
00559
00560 ERRORMSG("Overlapping domains in indexed assignment!"<<endl);
00561 PAssert(0);
00562 }
00563 }
00564
00565
00566 int tag = Ippl::Comm->next_tag( F_GEN_ASSIGN_TAG , F_TAG_CYCLE );
00567
00568
00569
00570 for_each(rhs.begin(), FillGCIfNecessary(lhs.getBareField()),
00571 PETE_NullCombiner());
00572
00573
00574
00575
00576 if (Ippl::getNodes() > 1) {
00577 TAU_PROFILE_START(sendtimer);
00578 IndexedSend(lhs,rhs,tag);
00579 TAU_PROFILE_STOP(sendtimer);
00580 }
00581
00582
00583
00584 multimap< NDIndex<D1> , LField<T1,D1>* , less< NDIndex<D1> > > recv_ac;
00585 int msgnum;
00586 if (Ippl::getNodes() > 1) {
00587 TAU_PROFILE_START(findtimer);
00588 CalcIndexedReceive(lhs,rhs,recv_ac,msgnum);
00589 TAU_PROFILE_STOP(findtimer);
00590 }
00591
00592
00593
00594 TAU_PROFILE_START(localstimer);
00595 IndexedLocalAssign(lhs,rhs,op);
00596 TAU_PROFILE_STOP(localstimer);
00597
00598
00599
00600 if (Ippl::getNodes() > 1) {
00601 TAU_PROFILE_START(rectimer);
00602 IndexedReceive(lhs,rhs,op,recv_ac,msgnum,tag);
00603 TAU_PROFILE_STOP(rectimer);
00604 }
00605
00606 lhs.getBareField().setDirtyFlag();
00607
00608
00609 TAU_PROFILE_START(filltimer);
00610 lhs.getBareField().fillGuardCellsIfNotDirty();
00611 TAU_PROFILE_STOP(filltimer);
00612
00613
00614 lhs.getBareField().Compress();
00615
00616
00617
00618 }
00619
00620
00621
00622
00623
00624