00001 #ifndef _AMPIIMPL_H
00002 #define _AMPIIMPL_H
00003
00004 #include <string.h>
00005 #include <algorithm>
00006 #include <numeric>
00007 #include <forward_list>
00008 #include <bitset>
00009
00010 #include "ampi.h"
00011 #include "ddt.h"
00012 #include "charm++.h"
00013
00014 using std::vector;
00015
00016
00017 #define AMPI_DEBUG(...) //CkPrintf(__VA_ARGS__)
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define STRINGIFY_INTERNAL(a) #a
00029 #define STRINGIFY(a) STRINGIFY_INTERNAL(a)
00030
00031 #if AMPI_HAVE_PMPI
00032 #define AMPI_API_IMPL(ret, name, ...) \
00033 _Pragma(STRINGIFY(weak name)) \
00034 _Pragma(STRINGIFY(weak P##name = name)) \
00035 CLINKAGE \
00036 ret name(__VA_ARGS__)
00037 #else // not Linux (no PMPI support):
00038 #define AMPI_API_IMPL(ret, name, ...) \
00039 CLINKAGE \
00040 ret name(__VA_ARGS__)
00041 #endif
00042
00043 extern char * ampi_binary_path;
00044
00045 #if AMPIMSGLOG
00046 #include "ckliststring.h"
00047 static CkListString msgLogRanks;
00048 static int msgLogWrite;
00049 static int msgLogRead;
00050 static char *msgLogFilename;
00051
00052 #if CMK_USE_ZLIB && 0
00053 #include <zlib.h>
00054 namespace PUP{
00055 class zdisk : public er {
00056 protected:
00057 gzFile F;
00058 zdisk(unsigned int type,gzFile f):er(type),F(f) {}
00059 zdisk(const zdisk &p);
00060 void operator=(const zdisk &p);
00061
00062
00063 virtual void impl_startSeek(seekBlock &s);
00064 virtual int impl_tell(seekBlock &s);
00065 virtual void impl_seek(seekBlock &s,int off);
00066 };
00067
00068
00069 class tozDisk : public zdisk {
00070 protected:
00071
00072 virtual void bytes(void *p,int n,size_t itemSize,dataType t);
00073 public:
00074
00075
00076
00077 tozDisk(gzFile f):zdisk(IS_PACKING,f) {}
00078 };
00079
00080
00081 class fromzDisk : public zdisk {
00082 protected:
00083
00084 virtual void bytes(void *p,int n,size_t itemSize,dataType t);
00085 public:
00086
00087
00088
00089 fromzDisk(gzFile f):zdisk(IS_UNPACKING,f) {}
00090 };
00091 };
00092 #endif
00093 #endif // AMPIMSGLOG
00094
00095
00096
00097 #ifndef AMPI_LOCAL_IMPL
00098 #define AMPI_LOCAL_IMPL ( !CMK_BIGSIM_CHARM && !CMK_TRACE_ENABLED )
00099 #endif
00100
00101
00102
00103 #ifndef AMPI_RDMA_IMPL
00104 #define AMPI_RDMA_IMPL ( !CMK_BIGSIM_CHARM && CMK_ONESIDED_IMPL && !CMK_CONVERSE_UGNI )
00105 #endif
00106
00107
00108 #ifndef AMPI_RDMA_THRESHOLD_DEFAULT
00109 #if CMK_USE_IBVERBS || CMK_OFI || CMK_CONVERSE_UGNI
00110 #define AMPI_RDMA_THRESHOLD_DEFAULT 65536
00111 #else
00112 #define AMPI_RDMA_THRESHOLD_DEFAULT 32768
00113 #endif
00114 #endif
00115
00116
00117
00118 #ifndef AMPI_SMP_RDMA_THRESHOLD_DEFAULT
00119 #define AMPI_SMP_RDMA_THRESHOLD_DEFAULT 16384
00120 #endif
00121
00122 extern int AMPI_RDMA_THRESHOLD;
00123 extern int AMPI_SMP_RDMA_THRESHOLD;
00124
00125 #define AMPI_ALLTOALL_THROTTLE 64
00126 #define AMPI_ALLTOALL_SHORT_MSG 256
00127 #if CMK_BIGSIM_CHARM
00128 #define AMPI_ALLTOALL_LONG_MSG 4194304
00129 #else
00130 #define AMPI_ALLTOALL_LONG_MSG 32768
00131 #endif
00132
00133 typedef void (*MPI_MigrateFn)(void);
00134
00135
00136
00137
00138
00139 #define AMM_TAG 0
00140 #define AMM_SRC 1
00141 #define AMM_NTAGS 2
00142
00143
00144 #ifndef AMPI_AMM_PT2PT_POOL_SIZE
00145 #define AMPI_AMM_PT2PT_POOL_SIZE 32
00146 #endif
00147
00148
00149 #ifndef AMPI_AMM_COLL_POOL_SIZE
00150 #define AMPI_AMM_COLL_POOL_SIZE 4
00151 #endif
00152
00153 class AmpiRequestList;
00154
00155 typedef void (*AmmPupMessageFn)(PUP::er& p, void **msg);
00156
00157 template <class T>
00158 class AmmEntry {
00159 public:
00160 int tags[AMM_NTAGS];
00161 AmmEntry<T>* next;
00162 T msg;
00163 AmmEntry(T m) noexcept { tags[AMM_TAG] = m->getTag(); tags[AMM_SRC] = m->getSrcRank(); next = NULL; msg = m; }
00164 AmmEntry(int tag, int src, T m) noexcept { tags[AMM_TAG] = tag; tags[AMM_SRC] = src; next = NULL; msg = m; }
00165 AmmEntry() = default;
00166 ~AmmEntry() = default;
00167 };
00168
00169 template <class T, size_t N>
00170 class Amm {
00171 public:
00172 AmmEntry<T>* first;
00173 AmmEntry<T>** lasth;
00174
00175 private:
00176 int startIdx;
00177 std::bitset<N> validEntries;
00178 std::array<AmmEntry<T>, N> entryPool;
00179
00180 public:
00181 Amm() noexcept : first(NULL), lasth(&first), startIdx(0) { validEntries.reset(); }
00182 ~Amm() = default;
00183 inline AmmEntry<T>* newEntry(int tag, int src, T msg) noexcept {
00184 if (validEntries.all()) {
00185 return new AmmEntry<T>(tag, src, msg);
00186 } else {
00187 for (int i=startIdx; i<validEntries.size(); i++) {
00188 if (!validEntries[i]) {
00189 validEntries[i] = 1;
00190 AmmEntry<T>* ent = new (&entryPool[i]) AmmEntry<T>(tag, src, msg);
00191 startIdx = i+1;
00192 return ent;
00193 }
00194 }
00195 CkAbort("AMPI> failed to find a free entry in pool!");
00196 return NULL;
00197 }
00198 }
00199 inline AmmEntry<T>* newEntry(T msg) noexcept {
00200 if (validEntries.all()) {
00201 return new AmmEntry<T>(msg);
00202 } else {
00203 for (int i=startIdx; i<validEntries.size(); i++) {
00204 if (!validEntries[i]) {
00205 validEntries[i] = 1;
00206 AmmEntry<T>* ent = new (&entryPool[i]) AmmEntry<T>(msg);
00207 startIdx = i+1;
00208 return ent;
00209 }
00210 }
00211 CkAbort("AMPI> failed to find a free entry in pool!");
00212 return NULL;
00213 }
00214 }
00215 inline void deleteEntry(AmmEntry<T> *ent) noexcept {
00216 if (ent >= &entryPool.front() && ent <= &entryPool.back()) {
00217 int idx = (int)((intptr_t)ent - (intptr_t)&entryPool.front()) / sizeof(AmmEntry<T>);
00218 validEntries[idx] = 0;
00219 startIdx = std::min(idx, startIdx);
00220 } else {
00221 delete ent;
00222 }
00223 }
00224 void freeAll() noexcept;
00225 void flushMsgs() noexcept;
00226 inline bool match(const int tags1[AMM_NTAGS], const int tags2[AMM_NTAGS]) const noexcept;
00227 inline void put(T msg) noexcept;
00228 inline void put(int tag, int src, T msg) noexcept;
00229 inline T get(int tag, int src, int* rtags=NULL) noexcept;
00230 inline T probe(int tag, int src, int* rtags) noexcept;
00231 inline int size() const noexcept;
00232 void pup(PUP::er& p, AmmPupMessageFn msgpup) noexcept;
00233 };
00234
00235 PUPfunctionpointer(MPI_User_function*)
00236
00237
00238
00239
00240
00241
00242 class OpStruct {
00243 public:
00244 MPI_User_function* func;
00245 bool isCommutative;
00246 private:
00247 bool isValid;
00248
00249 public:
00250 OpStruct() = default;
00251 OpStruct(MPI_User_function* f) noexcept : func(f), isCommutative(true), isValid(true) {}
00252 OpStruct(MPI_User_function* f, bool c) noexcept : func(f), isCommutative(c), isValid(true) {}
00253 void init(MPI_User_function* f, bool c) noexcept {
00254 func = f;
00255 isCommutative = c;
00256 isValid = true;
00257 }
00258 bool isFree() const noexcept { return !isValid; }
00259 void free() noexcept { isValid = false; }
00260 void pup(PUP::er &p) {
00261 p|func; p|isCommutative; p|isValid;
00262 }
00263 };
00264
00265 class AmpiOpHeader {
00266 public:
00267 MPI_User_function* func;
00268 MPI_Datatype dtype;
00269 int len;
00270 int szdata;
00271 AmpiOpHeader(MPI_User_function* f,MPI_Datatype d,int l,int szd) noexcept :
00272 func(f),dtype(d),len(l),szdata(szd) { }
00273 };
00274
00275
00276
00277 class WinStruct{
00278 public:
00279 MPI_Comm comm;
00280 int index;
00281
00282 private:
00283 bool areRecvsPosted;
00284 bool inEpoch;
00285 vector<int> exposureRankList;
00286 vector<int> accessRankList;
00287 vector<MPI_Request> requestList;
00288
00289 public:
00290 WinStruct() noexcept : comm(MPI_COMM_NULL), index(-1), areRecvsPosted(false), inEpoch(false) {
00291 exposureRankList.clear(); accessRankList.clear(); requestList.clear();
00292 }
00293 WinStruct(MPI_Comm comm_, int index_) noexcept : comm(comm_), index(index_), areRecvsPosted(false), inEpoch(false) {
00294 exposureRankList.clear(); accessRankList.clear(); requestList.clear();
00295 }
00296 void pup(PUP::er &p) noexcept {
00297 p|comm; p|index; p|areRecvsPosted; p|inEpoch; p|exposureRankList; p|accessRankList; p|requestList;
00298 }
00299 void clearEpochAccess() noexcept {
00300 accessRankList.clear(); inEpoch = false;
00301 }
00302 void clearEpochExposure() noexcept {
00303 exposureRankList.clear(); areRecvsPosted = false; requestList.clear(); inEpoch=false;
00304 }
00305 vector<int>& getExposureRankList() noexcept {return exposureRankList;}
00306 vector<int>& getAccessRankList() noexcept {return accessRankList;}
00307 void setExposureRankList(vector<int> &tmpExposureRankList) noexcept {exposureRankList = tmpExposureRankList;}
00308 void setAccessRankList(vector<int> &tmpAccessRankList) noexcept {accessRankList = tmpAccessRankList;}
00309 vector<int>& getRequestList() noexcept {return requestList;}
00310 bool AreRecvsPosted() const noexcept {return areRecvsPosted;}
00311 void setAreRecvsPosted(bool setR) noexcept {areRecvsPosted = setR;}
00312 bool isInEpoch() const noexcept {return inEpoch;}
00313 void setInEpoch(bool arg) noexcept {inEpoch = arg;}
00314 };
00315
00316 class lockQueueEntry {
00317 public:
00318 int requestRank;
00319 int lock_type;
00320 lockQueueEntry (int _requestRank, int _lock_type) noexcept
00321 : requestRank(_requestRank), lock_type(_lock_type) {}
00322 lockQueueEntry() = default;
00323 };
00324
00325 typedef CkQ<lockQueueEntry *> LockQueue;
00326
00327 class ampiParent;
00328
00329 class win_obj {
00330 public:
00331 void *baseAddr;
00332 MPI_Aint winSize;
00333 int disp_unit;
00334 MPI_Comm comm;
00335
00336 int owner;
00337 LockQueue lockQueue;
00338
00339
00340 std::string winName;
00341 bool initflag;
00342
00343 vector<int> keyvals;
00344
00345 void setName(const char *src) noexcept;
00346 void getName(char *src,int *len) noexcept;
00347
00348 public:
00349 void pup(PUP::er &p) noexcept;
00350
00351 win_obj() noexcept;
00352 win_obj(const char *name, void *base, MPI_Aint size, int disp_unit, MPI_Comm comm) noexcept;
00353 ~win_obj() noexcept;
00354
00355 int create(const char *name, void *base, MPI_Aint size, int disp_unit,
00356 MPI_Comm comm) noexcept;
00357 int free() noexcept;
00358
00359 vector<int>& getKeyvals() { return keyvals; }
00360
00361 int put(void *orgaddr, int orgcnt, int orgunit,
00362 MPI_Aint targdisp, int targcnt, int targunit) noexcept;
00363
00364 int get(void *orgaddr, int orgcnt, int orgunit,
00365 MPI_Aint targdisp, int targcnt, int targunit) noexcept;
00366 int accumulate(void *orgaddr, int count, MPI_Aint targdisp, MPI_Datatype targtype,
00367 MPI_Op op, ampiParent* pptr) noexcept;
00368
00369 int iget(int orgcnt, MPI_Datatype orgtype,
00370 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype) noexcept;
00371 int igetWait(MPI_Request *req, MPI_Status *status) noexcept;
00372 int igetFree(MPI_Request *req, MPI_Status *status) noexcept;
00373
00374 int fence() noexcept;
00375
00376 int lock(int requestRank, int lock_type) noexcept;
00377 int unlock(int requestRank) noexcept;
00378
00379 int wait() noexcept;
00380 int post() noexcept;
00381 int start() noexcept;
00382 int complete() noexcept;
00383
00384 void lockTopQueue() noexcept;
00385 void enqueue(int requestRank, int lock_type) noexcept;
00386 void dequeue() noexcept;
00387 bool emptyQueue() noexcept;
00388 };
00389
00390
00391 class KeyvalPair{
00392 protected:
00393 std::string key;
00394 std::string val;
00395 public:
00396 KeyvalPair() = default;
00397 KeyvalPair(const char* k, const char* v) noexcept;
00398 ~KeyvalPair() = default;
00399 void pup(PUP::er& p) noexcept {
00400 p|key;
00401 p|val;
00402 }
00403 friend class InfoStruct;
00404 };
00405
00406 class InfoStruct{
00407 CkPupPtrVec<KeyvalPair> nodes;
00408 bool valid;
00409 public:
00410 InfoStruct() noexcept : valid(true) { }
00411 void setvalid(bool valid_) noexcept { valid = valid_; }
00412 bool getvalid() const noexcept { return valid; }
00413 int set(const char* k, const char* v) noexcept;
00414 int dup(InfoStruct& src) noexcept;
00415 int get(const char* k, int vl, char*& v, int *flag) const noexcept;
00416 int deletek(const char* k) noexcept;
00417 int get_valuelen(const char* k, int* vl, int *flag) const noexcept;
00418 int get_nkeys(int *nkeys) const noexcept;
00419 int get_nthkey(int n,char* k) const noexcept;
00420 void myfree() noexcept;
00421 void pup(PUP::er& p) noexcept;
00422 };
00423
00424 class CProxy_ampi;
00425 class CProxyElement_ampi;
00426
00427
00428 class ampiTopology {
00429 private:
00430 vector<int> v;
00431
00432 public:
00433 virtual ~ampiTopology() noexcept {};
00434 virtual void pup(PUP::er &p) noexcept =0;
00435 virtual int getType() const noexcept =0;
00436 virtual void dup(ampiTopology* topo) noexcept =0;
00437 virtual const vector<int> &getnbors() const noexcept =0;
00438 virtual void setnbors(const vector<int> &nbors_) noexcept =0;
00439
00440 virtual const vector<int> &getdims() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00441 virtual const vector<int> &getperiods() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00442 virtual int getndims() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return -1;}
00443 virtual void setdims(const vector<int> &dims_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00444 virtual void setperiods(const vector<int> &periods_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00445 virtual void setndims(int ndims_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00446
00447 virtual int getnvertices() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return -1;}
00448 virtual const vector<int> &getindex() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00449 virtual const vector<int> &getedges() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00450 virtual void setnvertices(int nvertices_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00451 virtual void setindex(const vector<int> &index_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00452 virtual void setedges(const vector<int> &edges_) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00453
00454 virtual int getInDegree() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return -1;}
00455 virtual const vector<int> &getSources() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00456 virtual const vector<int> &getSourceWeights() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00457 virtual int getOutDegree() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return -1;}
00458 virtual const vector<int> &getDestinations() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00459 virtual const vector<int> &getDestWeights() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return v;}
00460 virtual bool areSourcesWeighted() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return false;}
00461 virtual bool areDestsWeighted() const noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class."); return false;}
00462 virtual void setAreSourcesWeighted(bool val) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00463 virtual void setAreDestsWeighted(bool val) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00464 virtual void setInDegree(int degree) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00465 virtual void setSources(const vector<int> &sources) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00466 virtual void setSourceWeights(const vector<int> &sourceWeights) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00467 virtual void setOutDegree(int degree) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00468 virtual void setDestinations(const vector<int> &destinations) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00469 virtual void setDestWeights(const vector<int> &destWeights) noexcept {CkAbort("AMPI: instance of invalid Virtual Topology class.");}
00470 };
00471
00472 class ampiCartTopology final : public ampiTopology {
00473 private:
00474 int ndims;
00475 vector<int> dims, periods, nbors;
00476
00477 public:
00478 ampiCartTopology() noexcept : ndims(-1) {}
00479
00480 void pup(PUP::er &p) noexcept {
00481 p|ndims;
00482 p|dims;
00483 p|periods;
00484 p|nbors;
00485 }
00486
00487 inline int getType() const noexcept {return MPI_CART;}
00488 inline void dup(ampiTopology* topo) noexcept {
00489 CkAssert(topo->getType() == MPI_CART);
00490 setndims(topo->getndims());
00491 setdims(topo->getdims());
00492 setperiods(topo->getperiods());
00493 setnbors(topo->getnbors());
00494 }
00495
00496 inline const vector<int> &getdims() const noexcept {return dims;}
00497 inline const vector<int> &getperiods() const noexcept {return periods;}
00498 inline int getndims() const noexcept {return ndims;}
00499 inline const vector<int> &getnbors() const noexcept {return nbors;}
00500
00501 inline void setdims(const vector<int> &d) noexcept {dims = d; dims.shrink_to_fit();}
00502 inline void setperiods(const vector<int> &p) noexcept {periods = p; periods.shrink_to_fit();}
00503 inline void setndims(int nd) noexcept {ndims = nd;}
00504 inline void setnbors(const vector<int> &n) noexcept {nbors = n; nbors.shrink_to_fit();}
00505 };
00506
00507 class ampiGraphTopology final : public ampiTopology {
00508 private:
00509 int nvertices;
00510 vector<int> index, edges, nbors;
00511
00512 public:
00513 ampiGraphTopology() noexcept : nvertices(-1) {}
00514
00515 void pup(PUP::er &p) noexcept {
00516 p|nvertices;
00517 p|index;
00518 p|edges;
00519 p|nbors;
00520 }
00521
00522 inline int getType() const noexcept {return MPI_GRAPH;}
00523 inline void dup(ampiTopology* topo) noexcept {
00524 CkAssert(topo->getType() == MPI_GRAPH);
00525 setnvertices(topo->getnvertices());
00526 setindex(topo->getindex());
00527 setedges(topo->getedges());
00528 setnbors(topo->getnbors());
00529 }
00530
00531 inline int getnvertices() const noexcept {return nvertices;}
00532 inline const vector<int> &getindex() const noexcept {return index;}
00533 inline const vector<int> &getedges() const noexcept {return edges;}
00534 inline const vector<int> &getnbors() const noexcept {return nbors;}
00535
00536 inline void setnvertices(int nv) noexcept {nvertices = nv;}
00537 inline void setindex(const vector<int> &i) noexcept {index = i; index.shrink_to_fit();}
00538 inline void setedges(const vector<int> &e) noexcept {edges = e; edges.shrink_to_fit();}
00539 inline void setnbors(const vector<int> &n) noexcept {nbors = n; nbors.shrink_to_fit();}
00540 };
00541
00542 class ampiDistGraphTopology final : public ampiTopology {
00543 private:
00544 int inDegree, outDegree;
00545 bool sourcesWeighted, destsWeighted;
00546 vector<int> sources, sourceWeights, destinations, destWeights, nbors;
00547
00548 public:
00549 ampiDistGraphTopology() noexcept : inDegree(-1), outDegree(-1), sourcesWeighted(false), destsWeighted(false) {}
00550
00551 void pup(PUP::er &p) noexcept {
00552 p|inDegree;
00553 p|outDegree;
00554 p|sourcesWeighted;
00555 p|destsWeighted;
00556 p|sources;
00557 p|sourceWeights;
00558 p|destinations;
00559 p|destWeights;
00560 p|nbors;
00561 }
00562
00563 inline int getType() const noexcept {return MPI_DIST_GRAPH;}
00564 inline void dup(ampiTopology* topo) noexcept {
00565 CkAssert(topo->getType() == MPI_DIST_GRAPH);
00566 setAreSourcesWeighted(topo->areSourcesWeighted());
00567 setAreDestsWeighted(topo->areDestsWeighted());
00568 setInDegree(topo->getInDegree());
00569 setSources(topo->getSources());
00570 setSourceWeights(topo->getSourceWeights());
00571 setOutDegree(topo->getOutDegree());
00572 setDestinations(topo->getDestinations());
00573 setDestWeights(topo->getDestWeights());
00574 setnbors(topo->getnbors());
00575 }
00576
00577 inline int getInDegree() const noexcept {return inDegree;}
00578 inline const vector<int> &getSources() const noexcept {return sources;}
00579 inline const vector<int> &getSourceWeights() const noexcept {return sourceWeights;}
00580 inline int getOutDegree() const noexcept {return outDegree;}
00581 inline const vector<int> &getDestinations() const noexcept {return destinations;}
00582 inline const vector<int> &getDestWeights() const noexcept {return destWeights;}
00583 inline bool areSourcesWeighted() const noexcept {return sourcesWeighted;}
00584 inline bool areDestsWeighted() const noexcept {return destsWeighted;}
00585 inline const vector<int> &getnbors() const noexcept {return nbors;}
00586
00587 inline void setAreSourcesWeighted(bool v) noexcept {sourcesWeighted = v ? 1 : 0;}
00588 inline void setAreDestsWeighted(bool v) noexcept {destsWeighted = v ? 1 : 0;}
00589 inline void setInDegree(int d) noexcept {inDegree = d;}
00590 inline void setSources(const vector<int> &s) noexcept {sources = s; sources.shrink_to_fit();}
00591 inline void setSourceWeights(const vector<int> &sw) noexcept {sourceWeights = sw; sourceWeights.shrink_to_fit();}
00592 inline void setOutDegree(int d) noexcept {outDegree = d;}
00593 inline void setDestinations(const vector<int> &d) noexcept {destinations = d; destinations.shrink_to_fit();}
00594 inline void setDestWeights(const vector<int> &dw) noexcept {destWeights = dw; destWeights.shrink_to_fit();}
00595 inline void setnbors(const vector<int> &nbors_) noexcept {nbors = nbors_; nbors.shrink_to_fit();}
00596 };
00597
00598
00599 class KeyvalNode {
00600 public:
00601 void *val;
00602 MPI_Copy_function *copy_fn;
00603 MPI_Delete_function *delete_fn;
00604 void *extra_state;
00605 int refCount;
00606 bool isValSet;
00607
00608 KeyvalNode() : val(NULL), copy_fn(NULL), delete_fn(NULL), extra_state(NULL), refCount(1), isValSet(false) { }
00609 KeyvalNode(MPI_Copy_function *cf, MPI_Delete_function *df, void* es) :
00610 val(NULL), copy_fn(cf), delete_fn(df), extra_state(es), refCount(1), isValSet(false) { }
00611 bool hasVal() const { return isValSet; }
00612 void clearVal() { isValSet = false; }
00613 void setVal(void *v) { val = v; isValSet = true; }
00614 void* getVal() const { return val; }
00615 void incRefCount() { refCount++; }
00616 int decRefCount() { CkAssert(refCount > 0); refCount--; return refCount; }
00617 void pup(PUP::er& p) {
00618 p((char *)val, sizeof(void *));
00619 p((char *)copy_fn, sizeof(void *));
00620 p((char *)delete_fn, sizeof(void *));
00621 p((char *)extra_state, sizeof(void *));
00622 p|refCount;
00623 p|isValSet;
00624 }
00625 };
00626
00627
00628
00629 class groupStruct {
00630 private:
00631 int sz;
00632 vector<int> ranks;
00633
00634 private:
00635 bool ranksIsIota() const noexcept {
00636 for (int i=0; i<ranks.size(); i++)
00637 if (ranks[i] != i)
00638 return false;
00639 return true;
00640 }
00641
00642 public:
00643 groupStruct() noexcept : sz(0) {}
00644 groupStruct(int s) noexcept : sz(s) {}
00645 groupStruct(vector<int> r) noexcept : sz(-1), ranks(std::move(r)) {
00646 if (ranksIsIota()) {
00647 sz = ranks.size();
00648 ranks.clear();
00649 }
00650 ranks.shrink_to_fit();
00651 }
00652 groupStruct &operator=(const groupStruct &obj) noexcept {
00653 sz = obj.sz;
00654 ranks = obj.ranks;
00655 return *this;
00656 }
00657 ~groupStruct() = default;
00658 void pup(PUP::er& p) noexcept {
00659 p|sz;
00660 p|ranks;
00661 }
00662 bool isIota() const noexcept {return (sz != -1);}
00663 int operator[](int i) const noexcept {return (isIota()) ? i : ranks[i];}
00664 int size() const noexcept {return (isIota()) ? sz : ranks.size();}
00665 vector<int> getRanks() const noexcept {
00666 if (isIota()) {
00667
00668 vector<int> tmpRanks(sz);
00669 std::iota(tmpRanks.begin(), tmpRanks.end(), 0);
00670 tmpRanks.shrink_to_fit();
00671 return tmpRanks;
00672 }
00673 else {
00674 return ranks;
00675 }
00676 }
00677 };
00678
00679 enum AmpiCommType : uint8_t {
00680 WORLD = 0
00681 ,INTRA = 1
00682 ,INTER = 2
00683 };
00684
00685
00686 class ampiCommStruct {
00687 private:
00688 MPI_Comm comm;
00689 CkArrayID ampiID;
00690 int size;
00691 AmpiCommType commType;
00692 groupStruct indices;
00693 groupStruct remoteIndices;
00694
00695 ampiTopology *ampiTopo;
00696 int topoType;
00697
00698
00699 vector<int> keyvals;
00700
00701
00702 std::string commName;
00703
00704 public:
00705 ampiCommStruct(int ignored=0) noexcept
00706 : size(-1), commType(INTRA), ampiTopo(NULL), topoType(MPI_UNDEFINED)
00707 {}
00708 ampiCommStruct(MPI_Comm comm_,const CkArrayID &id_,int size_) noexcept
00709 : comm(comm_), ampiID(id_),size(size_), commType(WORLD), indices(size_),
00710 ampiTopo(NULL), topoType(MPI_UNDEFINED)
00711 {}
00712 ampiCommStruct(MPI_Comm comm_,const CkArrayID &id_, const vector<int> &indices_) noexcept
00713 : comm(comm_), ampiID(id_), size(indices_.size()), commType(INTRA), indices(indices_),
00714 ampiTopo(NULL), topoType(MPI_UNDEFINED)
00715 {}
00716 ampiCommStruct(MPI_Comm comm_, const CkArrayID &id_, const vector<int> &indices_,
00717 const vector<int> &remoteIndices_) noexcept
00718 : comm(comm_), ampiID(id_), size(indices_.size()), commType(INTER), indices(indices_),
00719 remoteIndices(remoteIndices_), ampiTopo(NULL), topoType(MPI_UNDEFINED)
00720 {}
00721
00722 ~ampiCommStruct() noexcept {
00723 if (ampiTopo != NULL)
00724 delete ampiTopo;
00725 }
00726
00727
00728 ampiCommStruct(const ampiCommStruct &obj, int topoNumber=MPI_UNDEFINED) noexcept {
00729 switch (topoNumber) {
00730 case MPI_CART:
00731 ampiTopo = new ampiCartTopology();
00732 break;
00733 case MPI_GRAPH:
00734 ampiTopo = new ampiGraphTopology();
00735 break;
00736 case MPI_DIST_GRAPH:
00737 ampiTopo = new ampiDistGraphTopology();
00738 break;
00739 default:
00740 ampiTopo = NULL;
00741 break;
00742 }
00743 topoType = topoNumber;
00744 comm = obj.comm;
00745 ampiID = obj.ampiID;
00746 size = obj.size;
00747 commType = obj.commType;
00748 indices = obj.indices;
00749 remoteIndices = obj.remoteIndices;
00750 keyvals = obj.keyvals;
00751 commName = obj.commName;
00752 }
00753
00754 ampiCommStruct &operator=(const ampiCommStruct &obj) noexcept {
00755 if (this == &obj) {
00756 return *this;
00757 }
00758 switch (obj.topoType) {
00759 case MPI_CART:
00760 ampiTopo = new ampiCartTopology(*(static_cast<ampiCartTopology*>(obj.ampiTopo)));
00761 break;
00762 case MPI_GRAPH:
00763 ampiTopo = new ampiGraphTopology(*(static_cast<ampiGraphTopology*>(obj.ampiTopo)));
00764 break;
00765 case MPI_DIST_GRAPH:
00766 ampiTopo = new ampiDistGraphTopology(*(static_cast<ampiDistGraphTopology*>(obj.ampiTopo)));
00767 break;
00768 default:
00769 ampiTopo = NULL;
00770 break;
00771 }
00772 topoType = obj.topoType;
00773 comm = obj.comm;
00774 ampiID = obj.ampiID;
00775 size = obj.size;
00776 commType = obj.commType;
00777 indices = obj.indices;
00778 remoteIndices = obj.remoteIndices;
00779 keyvals = obj.keyvals;
00780 commName = obj.commName;
00781 return *this;
00782 }
00783
00784 const ampiTopology* getTopologyforNeighbors() const noexcept {
00785 return ampiTopo;
00786 }
00787
00788 ampiTopology* getTopology() noexcept {
00789 return ampiTopo;
00790 }
00791
00792 inline bool isinter() const noexcept {return commType==INTER;}
00793 void setArrayID(const CkArrayID &nID) noexcept {ampiID=nID;}
00794
00795 MPI_Comm getComm() const noexcept {return comm;}
00796 inline vector<int> getIndices() const noexcept {return indices.getRanks();}
00797 inline vector<int> getRemoteIndices() const noexcept {return remoteIndices.getRanks();}
00798 vector<int> &getKeyvals() noexcept {return keyvals;}
00799
00800 void setName(const char *src) noexcept {
00801 CkDDT_SetName(commName, src);
00802 }
00803
00804 void getName(char *name, int *len) const noexcept {
00805 int length = *len = commName.size();
00806 memcpy(name, commName.data(), length);
00807 name[length] = '\0';
00808 }
00809
00810
00811 CProxy_ampi getProxy() const noexcept;
00812
00813
00814 int getIndexForRank(int r) const noexcept {
00815 #if CMK_ERROR_CHECKING
00816 if (r>=size) CkAbort("AMPI> You passed in an out-of-bounds process rank!");
00817 #endif
00818 return indices[r];
00819 }
00820 int getIndexForRemoteRank(int r) const noexcept {
00821 #if CMK_ERROR_CHECKING
00822 if (r>=remoteIndices.size()) CkAbort("AMPI> You passed in an out-of-bounds intercomm remote process rank!");
00823 #endif
00824 return remoteIndices[r];
00825 }
00826
00827 int getRankForIndex(int i) const noexcept {
00828 if (indices.isIota()) return i;
00829 else {
00830 const vector<int>& ind = indices.getRanks();
00831 for (int r=0;r<ind.size();r++)
00832 if (ind[r]==i) return r;
00833 return -1;
00834 }
00835 }
00836
00837 int getSize() const noexcept {return size;}
00838
00839 void pup(PUP::er &p) noexcept {
00840 p|comm;
00841 p|ampiID;
00842 p|size;
00843 p|commType;
00844 p|indices;
00845 p|remoteIndices;
00846 p|keyvals;
00847 p|commName;
00848 p|topoType;
00849 if (topoType != MPI_UNDEFINED) {
00850 if (p.isUnpacking()) {
00851 switch (topoType) {
00852 case MPI_CART:
00853 ampiTopo = new ampiCartTopology();
00854 break;
00855 case MPI_GRAPH:
00856 ampiTopo = new ampiGraphTopology();
00857 break;
00858 case MPI_DIST_GRAPH:
00859 ampiTopo = new ampiDistGraphTopology();
00860 break;
00861 default:
00862 CkAbort("AMPI> Communicator has an invalid topology!");
00863 break;
00864 }
00865 }
00866 ampiTopo->pup(p);
00867 } else {
00868 ampiTopo = NULL;
00869 }
00870 if (p.isDeleting()) {
00871 delete ampiTopo; ampiTopo = NULL;
00872 }
00873 }
00874 };
00875 PUPmarshall(ampiCommStruct)
00876
00877 class mpi_comm_worlds{
00878 ampiCommStruct comms[MPI_MAX_COMM_WORLDS];
00879 public:
00880 ampiCommStruct &operator[](int i) noexcept {return comms[i];}
00881 void pup(PUP::er &p) noexcept {
00882 for (int i=0;i<MPI_MAX_COMM_WORLDS;i++)
00883 comms[i].pup(p);
00884 }
00885 };
00886
00887
00888 inline void outputOp(const vector<int>& vec) noexcept {
00889 if (vec.size() > 50) {
00890 CkPrintf("vector too large to output!\n");
00891 return;
00892 }
00893 CkPrintf("output vector: size=%d {",vec.size());
00894 for (int i=0; i<vec.size(); i++) {
00895 CkPrintf(" %d ", vec[i]);
00896 }
00897 CkPrintf("}\n");
00898 }
00899
00900 inline int getPosOp(int idx, const vector<int>& vec) noexcept {
00901 for (int r=0; r<vec.size(); r++) {
00902 if (vec[r] == idx) {
00903 return r;
00904 }
00905 }
00906 return MPI_UNDEFINED;
00907 }
00908
00909 inline vector<int> unionOp(const vector<int>& vec1, const vector<int>& vec2) noexcept {
00910 vector<int> newvec(vec1);
00911 for (int i=0; i<vec2.size(); i++) {
00912 if (getPosOp(vec2[i], vec1) == MPI_UNDEFINED) {
00913 newvec.push_back(vec2[i]);
00914 }
00915 }
00916 return newvec;
00917 }
00918
00919 inline vector<int> intersectOp(const vector<int>& vec1, const vector<int>& vec2) noexcept {
00920 vector<int> newvec;
00921 for (int i=0; i<vec1.size(); i++) {
00922 if (getPosOp(vec1[i], vec2) != MPI_UNDEFINED) {
00923 newvec.push_back(vec1[i]);
00924 }
00925 }
00926 return newvec;
00927 }
00928
00929 inline vector<int> diffOp(const vector<int>& vec1, const vector<int>& vec2) noexcept {
00930 vector<int> newvec;
00931 for (int i=0; i<vec1.size(); i++) {
00932 if (getPosOp(vec1[i], vec2) == MPI_UNDEFINED) {
00933 newvec.push_back(vec1[i]);
00934 }
00935 }
00936 return newvec;
00937 }
00938
00939 inline int* translateRanksOp(int n, const vector<int>& vec1, const int* ranks1,
00940 const vector<int>& vec2, int *ret) noexcept {
00941 for (int i=0; i<n; i++) {
00942 ret[i] = (ranks1[i] == MPI_PROC_NULL) ? MPI_PROC_NULL : getPosOp(vec1[ranks1[i]], vec2);
00943 }
00944 return ret;
00945 }
00946
00947 inline int compareVecOp(const vector<int>& vec1, const vector<int>& vec2) noexcept {
00948 int pos, ret = MPI_IDENT;
00949 if (vec1.size() != vec2.size()) {
00950 return MPI_UNEQUAL;
00951 }
00952 for (int i=0; i<vec1.size(); i++) {
00953 pos = getPosOp(vec1[i], vec2);
00954 if (pos == MPI_UNDEFINED) {
00955 return MPI_UNEQUAL;
00956 }
00957 else if (pos != i) {
00958 ret = MPI_SIMILAR;
00959 }
00960 }
00961 return ret;
00962 }
00963
00964 inline vector<int> inclOp(int n, const int* ranks, const vector<int>& vec) noexcept {
00965 vector<int> retvec(n);
00966 for (int i=0; i<n; i++) {
00967 retvec[i] = vec[ranks[i]];
00968 }
00969 return retvec;
00970 }
00971
00972 inline vector<int> exclOp(int n, const int* ranks, const vector<int>& vec) noexcept {
00973 vector<int> retvec;
00974 bool add = true;
00975 for (int j=0; j<vec.size(); j++) {
00976 for (int i=0; i<n; i++) {
00977 if (j == ranks[i]) {
00978 add = false;
00979 break;
00980 }
00981 }
00982 if (add) {
00983 retvec.push_back(vec[j]);
00984 }
00985 else {
00986 add = true;
00987 }
00988 }
00989 return retvec;
00990 }
00991
00992 inline vector<int> rangeInclOp(int n, int ranges[][3], const vector<int>& vec,
00993 int *flag) noexcept {
00994 vector<int> retvec;
00995 int first, last, stride;
00996 for (int i=0; i<n; i++) {
00997 first = ranges[i][0];
00998 last = ranges[i][1];
00999 stride = ranges[i][2];
01000 if (stride != 0) {
01001 for (int j=0; j<=(last-first)/stride; j++) {
01002 retvec.push_back(vec[first+stride*j]);
01003 }
01004 }
01005 else {
01006 *flag = MPI_ERR_ARG;
01007 return vector<int>();
01008 }
01009 }
01010 *flag = MPI_SUCCESS;
01011 return retvec;
01012 }
01013
01014 inline vector<int> rangeExclOp(int n, int ranges[][3], const vector<int>& vec,
01015 int *flag) noexcept {
01016 vector<int> ranks;
01017 int first, last, stride;
01018 for (int i=0; i<n; i++) {
01019 first = ranges[i][0];
01020 last = ranges[i][1];
01021 stride = ranges[i][2];
01022 if (stride != 0) {
01023 for (int j=0; j<=(last-first)/stride; j++) {
01024 ranks.push_back(first+stride*j);
01025 }
01026 }
01027 else {
01028 *flag = MPI_ERR_ARG;
01029 return vector<int>();
01030 }
01031 }
01032 *flag = MPI_SUCCESS;
01033 return exclOp(ranks.size(), &ranks[0], vec);
01034 }
01035
01036 #include "tcharm.h"
01037 #include "tcharmc.h"
01038
01039 #include "ampi.decl.h"
01040 #include "charm-api.h"
01041 #include <sys/stat.h>
01042
01043 extern int _mpi_nworlds;
01044
01045
01046 #define MPI_ATA_SEQ_TAG MPI_TAG_UB_VALUE+2
01047 #define MPI_BCAST_TAG MPI_TAG_UB_VALUE+3
01048 #define MPI_REDN_TAG MPI_TAG_UB_VALUE+4
01049 #define MPI_SCATTER_TAG MPI_TAG_UB_VALUE+5
01050 #define MPI_SCAN_TAG MPI_TAG_UB_VALUE+6
01051 #define MPI_EXSCAN_TAG MPI_TAG_UB_VALUE+7
01052 #define MPI_ATA_TAG MPI_TAG_UB_VALUE+8
01053 #define MPI_NBOR_TAG MPI_TAG_UB_VALUE+9
01054 #define MPI_RMA_TAG MPI_TAG_UB_VALUE+10
01055 #define MPI_EPOCH_START_TAG MPI_TAG_UB_VALUE+11
01056 #define MPI_EPOCH_END_TAG MPI_TAG_UB_VALUE+12
01057
01058 #define AMPI_COLL_SOURCE 0
01059 #define AMPI_COLL_COMM MPI_COMM_WORLD
01060
01061 enum AmpiReqType : uint8_t {
01062 AMPI_INVALID_REQ = 0,
01063 AMPI_I_REQ = 1,
01064 AMPI_ATA_REQ = 2,
01065 AMPI_SEND_REQ = 3,
01066 AMPI_SSEND_REQ = 4,
01067 AMPI_REDN_REQ = 5,
01068 AMPI_GATHER_REQ = 6,
01069 AMPI_GATHERV_REQ = 7,
01070 AMPI_G_REQ = 8,
01071 #if CMK_CUDA
01072 AMPI_GPU_REQ = 9
01073 #endif
01074 };
01075
01076 inline void operator|(PUP::er &p, AmpiReqType &r) {
01077 pup_bytes(&p, (void *)&r, sizeof(AmpiReqType));
01078 }
01079
01080 enum AmpiReqSts : char {
01081 AMPI_REQ_PENDING = 0,
01082 AMPI_REQ_BLOCKED = 1,
01083 AMPI_REQ_COMPLETED = 2
01084 };
01085
01086 enum AmpiSendType : bool {
01087 BLOCKING_SEND = false,
01088 I_SEND = true
01089 };
01090
01091 #define MyAlign8(x) (((x)+7)&(~7))
01092
01097 class AmpiRequest {
01098 public:
01099 void *buf = nullptr;
01100 int count = 0;
01101 MPI_Datatype type = MPI_DATATYPE_NULL;
01102 int tag = MPI_ANY_TAG;
01103 int src = MPI_ANY_SOURCE;
01104 MPI_Comm comm = MPI_COMM_NULL;
01105 MPI_Request reqIdx = MPI_REQUEST_NULL;
01106 bool complete = false;
01107 bool blocked = false;
01108
01109 #if CMK_BIGSIM_CHARM
01110 public:
01111 void *event = nullptr;
01112 int eventPe = -1;
01113 #endif
01114
01115 public:
01116 AmpiRequest() =default;
01117 virtual ~AmpiRequest() =default;
01118
01121 virtual void start(MPI_Request reqIdx) noexcept {}
01122
01124 virtual int getTag() const noexcept { return tag; }
01125 virtual int getSrcRank() const noexcept { return src; }
01126
01128 virtual bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept =0;
01129
01132 virtual int wait(MPI_Status *sts) noexcept =0;
01133
01136 virtual void cancel() noexcept {}
01137
01140 virtual void setPersistent(bool p) noexcept {}
01141 virtual bool isPersistent() const noexcept { return false; }
01142
01144 virtual void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept =0;
01145
01147 virtual void receive(ampi *ptr, CkReductionMsg *msg) noexcept =0;
01148
01150 virtual void receiveRdma(ampi *ptr, char *sbuf, int slength, int ssendReq,
01151 int srcRank, MPI_Comm scomm) noexcept { }
01152
01154 void setReqIdx(MPI_Request idx) noexcept { reqIdx = idx; }
01155 MPI_Request getReqIdx() const noexcept { return reqIdx; }
01156
01158 void free(CkDDT* ddt) noexcept {
01159 if (type != MPI_DATATYPE_NULL) ddt->freeType(type);
01160 }
01161
01163 void setBlocked(bool b) noexcept { blocked = b; }
01164 bool isBlocked() const noexcept { return blocked; }
01165
01169 virtual AmpiReqType getType() const noexcept =0;
01170
01174 virtual bool isUnmatched() const noexcept =0;
01175
01178 virtual bool isPooledType() const noexcept { return false; }
01179
01181 virtual int getNumReceivedBytes(CkDDT *ddt) const noexcept {
01182
01183 return count * ddt->getSize(type);
01184 }
01185
01186 virtual void pup(PUP::er &p) noexcept {
01187 p((char *)&buf, sizeof(void *));
01188 p(count);
01189 p(type);
01190 p(tag);
01191 p(src);
01192 p(comm);
01193 p(reqIdx);
01194 p(complete);
01195 p(blocked);
01196 #if CMK_BIGSIM_CHARM
01197
01198
01199
01200 p((char *)&event, sizeof(void *));
01201 p(eventPe);
01202 #endif
01203 }
01204
01205 virtual void print() const noexcept =0;
01206 };
01207
01208
01209
01210 #define AMPI_REQUEST_COMMON_INIT \
01211 { \
01212 complete = (sts_ == AMPI_REQ_COMPLETED); \
01213 blocked = (sts_ == AMPI_REQ_BLOCKED); \
01214 if (type_ != MPI_DATATYPE_NULL) { \
01215 ddt_->getType(type_)->incRefCount(); \
01216 } \
01217 }
01218
01219 class IReq final : public AmpiRequest {
01220 public:
01221 bool cancelled = false;
01222 bool persistent = false;
01223 int length = 0;
01224
01225 IReq(void *buf_, int count_, MPI_Datatype type_, int src_, int tag_,
01226 MPI_Comm comm_, CkDDT *ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01227 {
01228 buf = buf_;
01229 count = count_;
01230 type = type_;
01231 src = src_;
01232 tag = tag_;
01233 comm = comm_;
01234 AMPI_REQUEST_COMMON_INIT
01235 }
01236 IReq() =default;
01237 ~IReq() =default;
01238 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01239 int wait(MPI_Status *sts) noexcept override;
01240 void cancel() noexcept override { if (!complete) cancelled = true; }
01241 AmpiReqType getType() const noexcept override { return AMPI_I_REQ; }
01242 bool isUnmatched() const noexcept override { return !complete; }
01243 bool isPooledType() const noexcept override { return true; }
01244 void setPersistent(bool p) noexcept override { persistent = p; }
01245 bool isPersistent() const noexcept override { return persistent; }
01246 void start(MPI_Request reqIdx) noexcept override;
01247 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override;
01248 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override {}
01249 void receiveRdma(ampi *ptr, char *sbuf, int slength, int ssendReq, int srcRank, MPI_Comm scomm) noexcept override;
01250 int getNumReceivedBytes(CkDDT *ptr) const noexcept override {
01251 return length;
01252 }
01253 void pup(PUP::er &p) noexcept override {
01254 AmpiRequest::pup(p);
01255 p|cancelled;
01256 p|persistent;
01257 p|length;
01258 }
01259 void print() const noexcept override;
01260 };
01261
01262 class RednReq final : public AmpiRequest {
01263 public:
01264 MPI_Op op = MPI_OP_NULL;
01265
01266 RednReq(void *buf_, int count_, MPI_Datatype type_, MPI_Comm comm_,
01267 MPI_Op op_, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01268 {
01269 buf = buf_;
01270 count = count_;
01271 type = type_;
01272 src = AMPI_COLL_SOURCE;
01273 tag = MPI_REDN_TAG;
01274 comm = comm_;
01275 op = op_;
01276 AMPI_REQUEST_COMMON_INIT
01277 }
01278 RednReq() =default;
01279 ~RednReq() =default;
01280 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01281 int wait(MPI_Status *sts) noexcept override;
01282 void cancel() noexcept override {}
01283 AmpiReqType getType() const noexcept override { return AMPI_REDN_REQ; }
01284 bool isUnmatched() const noexcept override { return !complete; }
01285 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01286 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override;
01287 void pup(PUP::er &p) noexcept override {
01288 AmpiRequest::pup(p);
01289 p|op;
01290 }
01291 void print() const noexcept override;
01292 };
01293
01294 class GatherReq final : public AmpiRequest {
01295 public:
01296 GatherReq(void *buf_, int count_, MPI_Datatype type_, MPI_Comm comm_,
01297 CkDDT *ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01298 {
01299 buf = buf_;
01300 count = count_;
01301 type = type_;
01302 src = AMPI_COLL_SOURCE;
01303 tag = MPI_REDN_TAG;
01304 comm = comm_;
01305 AMPI_REQUEST_COMMON_INIT
01306 }
01307 GatherReq() =default;
01308 ~GatherReq() =default;
01309 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01310 int wait(MPI_Status *sts) noexcept override;
01311 void cancel() noexcept override {}
01312 AmpiReqType getType() const noexcept override { return AMPI_GATHER_REQ; }
01313 bool isUnmatched() const noexcept override { return !complete; }
01314 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01315 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override;
01316 void pup(PUP::er &p) noexcept override {
01317 AmpiRequest::pup(p);
01318 }
01319 void print() const noexcept override;
01320 };
01321
01322 class GathervReq final : public AmpiRequest {
01323 public:
01324 vector<int> recvCounts;
01325 vector<int> displs;
01326
01327 GathervReq(void *buf_, int count_, MPI_Datatype type_, MPI_Comm comm_, const int *rc,
01328 const int *d, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01329 {
01330 buf = buf_;
01331 count = count_;
01332 type = type_;
01333 src = AMPI_COLL_SOURCE;
01334 tag = MPI_REDN_TAG;
01335 comm = comm_;
01336 recvCounts.assign(rc, rc+count);
01337 displs.assign(d, d+count);
01338 AMPI_REQUEST_COMMON_INIT
01339 }
01340 GathervReq() =default;
01341 ~GathervReq() =default;
01342 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01343 int wait(MPI_Status *sts) noexcept override;
01344 AmpiReqType getType() const noexcept override { return AMPI_GATHERV_REQ; }
01345 bool isUnmatched() const noexcept override { return !complete; }
01346 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01347 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override;
01348 void pup(PUP::er &p) noexcept override {
01349 AmpiRequest::pup(p);
01350 p|recvCounts;
01351 p|displs;
01352 }
01353 void print() const noexcept override;
01354 };
01355
01356 class SendReq final : public AmpiRequest {
01357 bool persistent = false;
01358
01359 public:
01360 SendReq(MPI_Datatype type_, MPI_Comm comm_, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01361 {
01362 type = type_;
01363 comm = comm_;
01364 AMPI_REQUEST_COMMON_INIT
01365 }
01366 SendReq(void* buf_, int count_, MPI_Datatype type_, int dest_, int tag_,
01367 MPI_Comm comm_, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01368 {
01369 buf = buf_;
01370 count = count_;
01371 type = type_;
01372 src = dest_;
01373 tag = tag_;
01374 comm = comm_;
01375 AMPI_REQUEST_COMMON_INIT
01376 }
01377 SendReq() noexcept {}
01378 ~SendReq() noexcept {}
01379 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01380 int wait(MPI_Status *sts) noexcept override;
01381 void setPersistent(bool p) noexcept override { persistent = p; }
01382 bool isPersistent() const noexcept override { return persistent; }
01383 void start(MPI_Request reqIdx) noexcept override;
01384 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01385 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override {}
01386 AmpiReqType getType() const noexcept override { return AMPI_SEND_REQ; }
01387 bool isUnmatched() const noexcept override { return false; }
01388 bool isPooledType() const noexcept override { return true; }
01389 void pup(PUP::er &p) noexcept override {
01390 AmpiRequest::pup(p);
01391 p|persistent;
01392 }
01393 void print() const noexcept override;
01394 };
01395
01396 class SsendReq final : public AmpiRequest {
01397 private:
01398 bool persistent = false;
01399
01400 public:
01401 SsendReq(MPI_Datatype type_, MPI_Comm comm_, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01402 {
01403 type = type_;
01404 comm = comm_;
01405 AMPI_REQUEST_COMMON_INIT
01406 }
01407 SsendReq(void* buf_, int count_, MPI_Datatype type_, int dest_, int tag_, MPI_Comm comm_,
01408 CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01409 {
01410 buf = buf_;
01411 count = count_;
01412 type = type_;
01413 src = dest_;
01414 tag = tag_;
01415 comm = comm_;
01416 AMPI_REQUEST_COMMON_INIT
01417 }
01418 SsendReq(void* buf_, int count_, MPI_Datatype type_, int dest_, int tag_, MPI_Comm comm_,
01419 int src_, CkDDT* ddt_, AmpiReqSts sts_=AMPI_REQ_PENDING) noexcept
01420 {
01421 buf = buf_;
01422 count = count_;
01423 type = type_;
01424 src = dest_;
01425 tag = tag_;
01426 comm = comm_;
01427 AMPI_REQUEST_COMMON_INIT
01428 }
01429 SsendReq() =default;
01430 ~SsendReq() =default;
01431 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01432 int wait(MPI_Status *sts) noexcept override;
01433 void setPersistent(bool p) noexcept override { persistent = p; }
01434 bool isPersistent() const noexcept override { return persistent; }
01435 void start(MPI_Request reqIdx) noexcept override;
01436 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01437 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override {}
01438 AmpiReqType getType() const noexcept override { return AMPI_SSEND_REQ; }
01439 bool isUnmatched() const noexcept override { return false; }
01440 bool isPooledType() const noexcept override { return true; }
01441 void pup(PUP::er &p) noexcept override {
01442 AmpiRequest::pup(p);
01443 p|persistent;
01444 }
01445 void print() const noexcept override;
01446 };
01447
01448 #if CMK_CUDA
01449 class GPUReq : public AmpiRequest {
01450 public:
01451 GPUReq() noexcept;
01452 ~GPUReq() =default;
01453 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01454 int wait(MPI_Status *sts) noexcept override;
01455 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override;
01456 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override;
01457 AmpiReqType getType() const noexcept override { return AMPI_GPU_REQ; }
01458 bool isUnmatched() const noexcept override { return false; }
01459 void setComplete() noexcept;
01460 void print() const noexcept override;
01461 };
01462 #endif
01463
01464 class ATAReq final : public AmpiRequest {
01465 public:
01466 vector<MPI_Request> reqs;
01467
01468 ATAReq(int numReqs_) noexcept : reqs(numReqs_) {}
01469 ATAReq() =default;
01470 ~ATAReq() =default;
01471 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01472 int wait(MPI_Status *sts) noexcept override;
01473 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01474 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override {}
01475 int getCount() const noexcept { return reqs.size(); }
01476 AmpiReqType getType() const noexcept override { return AMPI_ATA_REQ; }
01477 bool isUnmatched() const noexcept override { return false; }
01478 void pup(PUP::er &p) noexcept override {
01479 AmpiRequest::pup(p);
01480 p|reqs;
01481 }
01482 void print() const noexcept override;
01483 };
01484
01485 class GReq final : public AmpiRequest {
01486 private:
01487 MPI_Grequest_query_function* queryFn;
01488 MPI_Grequest_free_function* freeFn;
01489 MPI_Grequest_cancel_function* cancelFn;
01490 MPIX_Grequest_poll_function* pollFn;
01491 MPIX_Grequest_wait_function* waitFn;
01492 void* extraState;
01493
01494 public:
01495 GReq(MPI_Grequest_query_function* q, MPI_Grequest_free_function* f, MPI_Grequest_cancel_function* c, void* es) noexcept
01496 : queryFn(q), freeFn(f), cancelFn(c), pollFn(nullptr), waitFn(nullptr), extraState(es) {}
01497 GReq(MPI_Grequest_query_function *q, MPI_Grequest_free_function* f, MPI_Grequest_cancel_function* c, MPIX_Grequest_poll_function* p, void* es) noexcept
01498 : queryFn(q), freeFn(f), cancelFn(c), pollFn(p), waitFn(nullptr), extraState(es) {}
01499 GReq(MPI_Grequest_query_function *q, MPI_Grequest_free_function* f, MPI_Grequest_cancel_function* c, MPIX_Grequest_poll_function* p, MPIX_Grequest_wait_function* w, void* es) noexcept
01500 : queryFn(q), freeFn(f), cancelFn(c), pollFn(p), waitFn(w), extraState(es) {}
01501 GReq() =default;
01502 ~GReq() noexcept { (*freeFn)(extraState); }
01503 bool test(MPI_Status *sts=MPI_STATUS_IGNORE) noexcept override;
01504 int wait(MPI_Status *sts) noexcept override;
01505 void receive(ampi *ptr, AmpiMsg *msg, bool deleteMsg=true) noexcept override {}
01506 void receive(ampi *ptr, CkReductionMsg *msg) noexcept override {}
01507 void cancel() noexcept override { (*cancelFn)(extraState, complete); }
01508 AmpiReqType getType() const noexcept override { return AMPI_G_REQ; }
01509 bool isUnmatched() const noexcept override { return false; }
01510 void pup(PUP::er &p) noexcept override {
01511 AmpiRequest::pup(p);
01512 p((char *)queryFn, sizeof(void *));
01513 p((char *)freeFn, sizeof(void *));
01514 p((char *)cancelFn, sizeof(void *));
01515 p((char *)pollFn, sizeof(void *));
01516 p((char *)waitFn, sizeof(void *));
01517 p((char *)extraState, sizeof(void *));
01518 }
01519 void print() const noexcept override;
01520 };
01521
01522 class AmpiRequestPool;
01523
01524 class AmpiRequestList {
01525 private:
01526 vector<AmpiRequest*> reqs;
01527 int startIdx;
01528 AmpiRequestPool* reqPool;
01529 public:
01530 AmpiRequestList() noexcept : startIdx(0) {}
01531 AmpiRequestList(int size, AmpiRequestPool* reqPoolPtr) noexcept
01532 : reqs(size), startIdx(0), reqPool(reqPoolPtr) {}
01533 ~AmpiRequestList() noexcept {}
01534
01535 inline AmpiRequest* operator[](int n) noexcept {
01536 #if CMK_ERROR_CHECKING
01537 return reqs.at(n);
01538 #else
01539 return reqs[n];
01540 #endif
01541 }
01542 void free(AmpiRequestPool& reqPool, int idx, CkDDT *ddt) noexcept;
01543 void freeNonPersReq(int &idx) noexcept;
01544 inline int insert(AmpiRequest* req) noexcept {
01545 for (int i=startIdx; i<reqs.size(); i++) {
01546 if (reqs[i] == NULL) {
01547 req->setReqIdx(i);
01548 reqs[i] = req;
01549 startIdx = i+1;
01550 return i;
01551 }
01552 }
01553 reqs.push_back(req);
01554 int idx = reqs.size()-1;
01555 req->setReqIdx(idx);
01556 startIdx = idx+1;
01557 return idx;
01558 }
01559
01560 inline void checkRequest(MPI_Request idx) const noexcept {
01561 if (idx != MPI_REQUEST_NULL && (idx < 0 || idx >= reqs.size()))
01562 CkAbort("Invalid MPI_Request\n");
01563 }
01564
01565 inline void unblockReqs(MPI_Request *requests, int numReqs) noexcept {
01566 for (int i=0; i<numReqs; i++) {
01567 if (requests[i] != MPI_REQUEST_NULL) {
01568 reqs[requests[i]]->setBlocked(false);
01569 }
01570 }
01571 }
01572
01573 void pup(PUP::er &p, AmpiRequestPool* reqPool) noexcept;
01574
01575 void print() const noexcept {
01576 for (int i=0; i<reqs.size(); i++) {
01577 if (reqs[i] == NULL) continue;
01578 CkPrintf("AmpiRequestList Element %d [%p]: \n", i+1, reqs[i]);
01579 reqs[i]->print();
01580 }
01581 }
01582 };
01583
01584
01585 class memBuf {
01586 CkVec<char> buf;
01587 public:
01588 memBuf() =default;
01589 memBuf(int size) noexcept : buf(size) {}
01590 void setSize(int s) noexcept {buf.resize(s);}
01591 int getSize() const noexcept {return buf.size();}
01592 const void *getData() const noexcept {return (const void *)&buf[0];}
01593 void *getData() noexcept {return (void *)&buf[0];}
01594 };
01595
01596 template <class T>
01597 inline void pupIntoBuf(memBuf &b,T &t) noexcept {
01598 PUP::sizer ps;ps|t;
01599 b.setSize(ps.size());
01600 PUP::toMem pm(b.getData()); pm|t;
01601 }
01602
01603 template <class T>
01604 inline void pupFromBuf(const void *data,T &t) noexcept {
01605 PUP::fromMem p(data); p|t;
01606 }
01607
01608 #define COLL_SEQ_IDX -1
01609
01610 class AmpiMsgPool;
01611
01612 class AmpiMsg final : public CMessage_AmpiMsg {
01613 private:
01614 int ssendReq;
01615 int tag;
01616 int srcRank;
01617 int length;
01618 int origLength;
01619 MPI_Comm comm;
01620 public:
01621 char *data;
01622 #if CMK_BIGSIM_CHARM
01623 public:
01624 void *event;
01625 int eventPe;
01626 #endif
01627
01628 public:
01629 AmpiMsg() noexcept { data = NULL; }
01630 AmpiMsg(int sreq, int t, int sRank, int l) noexcept :
01631 ssendReq(sreq), tag(t), srcRank(sRank), length(l), origLength(l)
01632 { }
01633 AmpiMsg(CMK_REFNUM_TYPE seq, int sreq, int t, int sRank, int l) noexcept :
01634 ssendReq(sreq), tag(t), srcRank(sRank), length(l), origLength(l)
01635 { CkSetRefNum(this, seq); }
01636 inline void setSsendReq(int s) noexcept { CkAssert(s >= 0); ssendReq = s; }
01637 inline void setSeq(CMK_REFNUM_TYPE s) noexcept { CkAssert(s >= 0); UsrToEnv(this)->setRef(s); }
01638 inline void setSrcRank(int sr) noexcept { srcRank = sr; }
01639 inline void setLength(int l) noexcept { length = l; }
01640 inline void setTag(int t) noexcept { tag = t; }
01641 inline void setComm(MPI_Comm c) noexcept { comm = c; }
01642 inline CMK_REFNUM_TYPE getSeq() const noexcept { return UsrToEnv(this)->getRef(); }
01643 inline int getSsendReq() const noexcept { return ssendReq; }
01644 inline int getSeqIdx() const noexcept {
01645
01646 if (tag >= MPI_BCAST_TAG && tag <= MPI_ATA_TAG) {
01647 return COLL_SEQ_IDX;
01648 }
01649 else {
01650 return srcRank;
01651 }
01652 }
01653 inline int getSrcRank() const noexcept { return srcRank; }
01654 inline int getLength() const noexcept { return length; }
01655 inline char* getData() const noexcept { return data; }
01656 inline int getTag() const noexcept { return tag; }
01657 inline MPI_Comm getComm() const noexcept { return comm; }
01658 static AmpiMsg* pup(PUP::er &p, AmpiMsg *m) noexcept
01659 {
01660 int ref, ssendReq, tag, srcRank, length, origLength;
01661 MPI_Comm comm;
01662 if(p.isPacking() || p.isSizing()) {
01663 ref = CkGetRefNum(m);
01664 ssendReq = m->ssendReq;
01665 tag = m->tag;
01666 srcRank = m->srcRank;
01667 length = m->length;
01668 origLength = m->origLength;
01669 comm = m->comm;
01670 }
01671 p(ref); p(ssendReq); p(tag); p(srcRank); p(length); p(origLength); p(comm);
01672 if(p.isUnpacking()) {
01673 m = new (origLength, 0) AmpiMsg(ref, ssendReq, tag, srcRank, origLength);
01674 m->setLength(length);
01675 m->setComm(comm);
01676 }
01677 p(m->data, length);
01678 if(p.isDeleting()) {
01679 delete m;
01680 m = 0;
01681 }
01682 return m;
01683 }
01684
01685 friend AmpiMsgPool;
01686 };
01687
01688 #define AMPI_MSG_POOL_SIZE 32 // Max # of AmpiMsg's allowed in the pool
01689 #define AMPI_POOLED_MSG_SIZE 64 // Max # of Bytes in pooled msgs' payload
01690
01691 class AmpiMsgPool {
01692 private:
01693 std::forward_list<AmpiMsg *> msgs;
01694 int msgLength;
01695 int maxMsgs;
01696 int currMsgs;
01697
01698 public:
01699 AmpiMsgPool(int _numMsgs = 0, int _msgLength = 0) noexcept
01700 : msgLength(_msgLength), maxMsgs(_numMsgs), currMsgs(0) {}
01701 ~AmpiMsgPool() =default;
01702 inline void clear() noexcept {
01703 while (!msgs.empty()) {
01704 delete msgs.front();
01705 msgs.pop_front();
01706 }
01707 currMsgs = 0;
01708 }
01709 inline AmpiMsg* newAmpiMsg(CMK_REFNUM_TYPE seq, int ssendReq, int tag, int srcRank, int len) noexcept {
01710 if (msgs.empty() || msgs.front()->origLength < len) {
01711 int newlen = std::max(msgLength, len);
01712 AmpiMsg* msg = new (newlen, 0) AmpiMsg(seq, ssendReq, tag, srcRank, newlen);
01713 msg->setLength(len);
01714 return msg;
01715 } else {
01716 AmpiMsg* msg = msgs.front();
01717 msgs.pop_front();
01718 currMsgs--;
01719 msg->setSeq(seq);
01720 msg->setSsendReq(ssendReq);
01721 msg->setTag(tag);
01722 msg->setSrcRank(srcRank);
01723 msg->setLength(len);
01724 return msg;
01725 }
01726 }
01727 inline void deleteAmpiMsg(AmpiMsg* msg) noexcept {
01728
01729
01730 if (currMsgs != maxMsgs && msg->origLength >= msgLength && msg->origLength < 2*msgLength) {
01731 msgs.push_front(msg);
01732 currMsgs++;
01733 } else {
01734 delete msg;
01735 }
01736 }
01737 void pup(PUP::er& p) {
01738 p|msgLength;
01739 p|maxMsgs;
01740
01741 }
01742 };
01743
01744
01745 #ifndef AMPI_REQ_POOL_SIZE
01746 #define AMPI_REQ_POOL_SIZE 64
01747 #endif
01748
01749
01750 #define DefinePooledReqX(name, func) \
01751 static const size_t ireq##name = func(IReq); \
01752 static const size_t sreq##name = func(SendReq); \
01753 static const size_t ssreq##name = func(SsendReq); \
01754 static const size_t pooledReq##name = (ireq##name >= sreq##name && ireq##name >= ssreq##name) ? ireq##name : \
01755 (sreq##name >= ireq##name && sreq##name >= ssreq##name) ? sreq##name : \
01756 (ssreq##name);
01757
01758
01759 DefinePooledReqX(Size, sizeof)
01760
01761
01762 DefinePooledReqX(Align, alignof)
01763
01764
01765
01766
01767
01768
01769 class AmpiRequestPool {
01770 private:
01771 std::bitset<AMPI_REQ_POOL_SIZE> validReqs;
01772 int startIdx = 0;
01773 alignas(pooledReqAlign) std::array<char, AMPI_REQ_POOL_SIZE*pooledReqSize> reqs;
01774
01775 public:
01776 AmpiRequestPool() =default;
01777 ~AmpiRequestPool() =default;
01778 template <typename T, typename... Args>
01779 inline T* newReq(Args&&... args) noexcept {
01780 if (validReqs.all()) {
01781 return new T(std::forward<Args>(args)...);
01782 } else {
01783 for (int i=startIdx; i<validReqs.size(); i++) {
01784 if (!validReqs[i]) {
01785 validReqs[i] = 1;
01786 startIdx = i+1;
01787 T* req = new (&reqs[i*pooledReqSize]) T(std::forward<Args>(args)...);
01788 return req;
01789 }
01790 }
01791 CkAbort("AMPI> failed to find a free request in pool!");
01792 return NULL;
01793 }
01794 }
01795 inline void deleteReq(AmpiRequest* req) noexcept {
01796 if (req->isPooledType() &&
01797 ((char*)req >= &reqs.front() && (char*)req <= &reqs.back()))
01798 {
01799 int idx = (int)((intptr_t)req - (intptr_t)&reqs[0]) / pooledReqSize;
01800 validReqs[idx] = 0;
01801 startIdx = std::min(idx, startIdx);
01802 } else {
01803 delete req;
01804 }
01805 }
01806 void pup(PUP::er& p) noexcept {
01807
01808
01809 }
01810 };
01811
01818 class AmpiOtherElement {
01819 private:
01821 CMK_REFNUM_TYPE seqIncoming, seqOutgoing;
01822
01824 uint16_t numOutOfOrder;
01825
01826 public:
01829 AmpiOtherElement() noexcept : seqIncoming(1), seqOutgoing(0), numOutOfOrder(0) {}
01830
01832 inline void incSeqIncoming() noexcept { seqIncoming++; if (seqIncoming==0) seqIncoming=1; }
01833 inline CMK_REFNUM_TYPE getSeqIncoming() const noexcept { return seqIncoming; }
01834
01835 inline void incSeqOutgoing() noexcept { seqOutgoing++; if (seqOutgoing==0) seqOutgoing=1; }
01836 inline CMK_REFNUM_TYPE getSeqOutgoing() const noexcept { return seqOutgoing; }
01837
01838 inline void incNumOutOfOrder() noexcept { numOutOfOrder++; }
01839 inline void decNumOutOfOrder() noexcept { numOutOfOrder--; }
01840 inline uint16_t getNumOutOfOrder() const noexcept { return numOutOfOrder; }
01841 };
01842 PUPbytes(AmpiOtherElement)
01843
01844 class AmpiSeqQ : private CkNoncopyable {
01845 CkMsgQ<AmpiMsg> out;
01846 std::unordered_map<int, AmpiOtherElement> elements;
01847
01848 public:
01849 AmpiSeqQ() =default;
01850 AmpiSeqQ(int commSize) noexcept {
01851 elements.reserve(std::min(commSize, 64));
01852 }
01853 ~AmpiSeqQ() =default;
01854 void pup(PUP::er &p) noexcept;
01855
01862 inline int put(int seqIdx, AmpiMsg *msg) noexcept {
01863 AmpiOtherElement &el = elements[seqIdx];
01864 if (msg->getSeq() == el.getSeqIncoming()) {
01865 el.incSeqIncoming();
01866 return 1+el.getNumOutOfOrder();
01867 }
01868 else {
01869 putOutOfOrder(seqIdx, msg);
01870 return 0;
01871 }
01872 }
01873
01877 inline int isInOrder(int srcRank, CMK_REFNUM_TYPE seq) noexcept {
01878 AmpiOtherElement &el = elements[srcRank];
01879 if (seq == el.getSeqIncoming()) {
01880 el.incSeqIncoming();
01881 return 1+el.getNumOutOfOrder();
01882 }
01883 else {
01884 return 0;
01885 }
01886 }
01887
01890 AmpiMsg *getOutOfOrder(int seqIdx) noexcept;
01891
01893 void putOutOfOrder(int seqIdx, AmpiMsg *msg) noexcept;
01894
01896 inline void incCollSeqOutgoing() noexcept {
01897 elements[COLL_SEQ_IDX].incSeqOutgoing();
01898 }
01899
01901 inline CMK_REFNUM_TYPE nextOutgoing(int destRank) noexcept {
01902 AmpiOtherElement &el = elements[destRank];
01903 el.incSeqOutgoing();
01904 return el.getSeqOutgoing();
01905 }
01906 };
01907 PUPmarshall(AmpiSeqQ)
01908
01909
01910 inline CProxy_ampi ampiCommStruct::getProxy() const noexcept {return ampiID;}
01911 const ampiCommStruct &universeComm2CommStruct(MPI_Comm universeNo) noexcept;
01912
01913
01914 #define AMPI_MAX_PREDEFINED_OP 13
01915
01916
01917
01918
01919
01920 class ampiParent final : public CBase_ampiParent {
01921 private:
01922 TCharm *thread;
01923 CProxy_TCharm threads;
01924
01925 public:
01926 int numBlockedReqs;
01927 bool resumeOnRecv, resumeOnColl;
01928 AmpiRequestList ampiReqs;
01929 AmpiRequestPool reqPool;
01930 AmpiRequest *blockingReq;
01931 CkDDT myDDT;
01932
01933 private:
01934 MPI_Comm worldNo;
01935 ampi *worldPtr;
01936
01937 CkPupPtrVec<ampiCommStruct> splitComm;
01938 CkPupPtrVec<ampiCommStruct> groupComm;
01939 CkPupPtrVec<ampiCommStruct> cartComm;
01940 CkPupPtrVec<ampiCommStruct> graphComm;
01941 CkPupPtrVec<ampiCommStruct> distGraphComm;
01942 CkPupPtrVec<ampiCommStruct> interComm;
01943 CkPupPtrVec<ampiCommStruct> intraComm;
01944
01945 CkPupPtrVec<groupStruct> groups;
01946 CkPupPtrVec<WinStruct> winStructList;
01947 CkPupPtrVec<InfoStruct> infos;
01948 const std::array<MPI_User_function*, AMPI_MAX_PREDEFINED_OP+1>& predefinedOps;
01949 vector<OpStruct> userOps;
01950 vector<AmpiMsg *> matchedMsgs;
01951
01952
01953
01954
01955
01956 int* kv_builtin_storage;
01957 MPI_Aint* win_size_storage;
01958 void** win_base_storage;
01959 CkPupPtrVec<KeyvalNode> kvlist;
01960 void* bsendBuffer;
01961 int bsendBufferSize;
01962
01963
01964 bool isTmpRProxySet;
01965 CProxy_ampi tmpRProxy;
01966
01967 MPI_MigrateFn userAboutToMigrateFn, userJustMigratedFn;
01968
01969 public:
01970 bool ampiInitCallDone;
01971
01972 private:
01973 bool kv_set_builtin(int keyval, void* attribute_val) noexcept;
01974 bool kv_get_builtin(int keyval) noexcept;
01975
01976 public:
01977 void prepareCtv() noexcept;
01978
01979 MPI_Message putMatchedMsg(AmpiMsg* msg) noexcept {
01980
01981 for (int i=0; i<matchedMsgs.size(); i++) {
01982 if (matchedMsgs[i] == NULL) {
01983 matchedMsgs[i] = msg;
01984 return i;
01985 }
01986 }
01987
01988 matchedMsgs.push_back(msg);
01989 return matchedMsgs.size() - 1;
01990 }
01991 AmpiMsg* getMatchedMsg(MPI_Message message) noexcept {
01992 if (message == MPI_MESSAGE_NO_PROC || message == MPI_MESSAGE_NULL) {
01993 return NULL;
01994 }
01995 CkAssert(message >= 0 && message < matchedMsgs.size());
01996 AmpiMsg* msg = matchedMsgs[message];
01997
01998 matchedMsgs[message] = NULL;
01999 while (matchedMsgs.back() == NULL) {
02000 matchedMsgs.pop_back();
02001 }
02002 return msg;
02003 }
02004
02005 inline void attachBuffer(void *buffer, int size) noexcept {
02006 bsendBuffer = buffer;
02007 bsendBufferSize = size;
02008 }
02009 inline void detachBuffer(void *buffer, int *size) noexcept {
02010 *(void **)buffer = bsendBuffer;
02011 *size = bsendBufferSize;
02012 }
02013 inline bool isSplit(MPI_Comm comm) const noexcept {
02014 return (comm>=MPI_COMM_FIRST_SPLIT && comm<MPI_COMM_FIRST_GROUP);
02015 }
02016 const ampiCommStruct &getSplit(MPI_Comm comm) const noexcept {
02017 int idx=comm-MPI_COMM_FIRST_SPLIT;
02018 if (idx>=splitComm.size()) CkAbort("Bad split communicator used");
02019 return *splitComm[idx];
02020 }
02021 void splitChildRegister(const ampiCommStruct &s) noexcept;
02022
02023 inline bool isGroup(MPI_Comm comm) const noexcept {
02024 return (comm>=MPI_COMM_FIRST_GROUP && comm<MPI_COMM_FIRST_CART);
02025 }
02026 const ampiCommStruct &getGroup(MPI_Comm comm) const noexcept {
02027 int idx=comm-MPI_COMM_FIRST_GROUP;
02028 if (idx>=groupComm.size()) CkAbort("Bad group communicator used");
02029 return *groupComm[idx];
02030 }
02031 void groupChildRegister(const ampiCommStruct &s) noexcept;
02032 inline bool isInGroups(MPI_Group group) const noexcept {
02033 return (group>=0 && group<groups.size());
02034 }
02035
02036 void cartChildRegister(const ampiCommStruct &s) noexcept;
02037 void graphChildRegister(const ampiCommStruct &s) noexcept;
02038 void distGraphChildRegister(const ampiCommStruct &s) noexcept;
02039 void interChildRegister(const ampiCommStruct &s) noexcept;
02040 void intraChildRegister(const ampiCommStruct &s) noexcept;
02041
02042 public:
02043 ampiParent(MPI_Comm worldNo_,CProxy_TCharm threads_,int nRanks_) noexcept;
02044 ampiParent(CkMigrateMessage *msg) noexcept;
02045 void ckAboutToMigrate() noexcept;
02046 void ckJustMigrated() noexcept;
02047 void ckJustRestored() noexcept;
02048 void setUserAboutToMigrateFn(MPI_MigrateFn f) noexcept;
02049 void setUserJustMigratedFn(MPI_MigrateFn f) noexcept;
02050 ~ampiParent() noexcept;
02051
02052
02053 TCharm *registerAmpi(ampi *ptr,ampiCommStruct s,bool forMigration) noexcept;
02054
02055
02056 void ExchangeProxy(CProxy_ampi rproxy) noexcept {
02057 if(!isTmpRProxySet){ tmpRProxy=rproxy; isTmpRProxySet=true; }
02058 else{ tmpRProxy.setRemoteProxy(rproxy); rproxy.setRemoteProxy(tmpRProxy); isTmpRProxySet=false; }
02059 }
02060
02061
02062 MPI_Comm getNextSplit() const noexcept {return MPI_COMM_FIRST_SPLIT+splitComm.size();}
02063 MPI_Comm getNextGroup() const noexcept {return MPI_COMM_FIRST_GROUP+groupComm.size();}
02064 MPI_Comm getNextCart() const noexcept {return MPI_COMM_FIRST_CART+cartComm.size();}
02065 MPI_Comm getNextGraph() const noexcept {return MPI_COMM_FIRST_GRAPH+graphComm.size();}
02066 MPI_Comm getNextDistGraph() const noexcept {return MPI_COMM_FIRST_DIST_GRAPH+distGraphComm.size();}
02067 MPI_Comm getNextInter() const noexcept {return MPI_COMM_FIRST_INTER+interComm.size();}
02068 MPI_Comm getNextIntra() const noexcept {return MPI_COMM_FIRST_INTRA+intraComm.size();}
02069
02070 inline bool isCart(MPI_Comm comm) const noexcept {
02071 return (comm>=MPI_COMM_FIRST_CART && comm<MPI_COMM_FIRST_GRAPH);
02072 }
02073 ampiCommStruct &getCart(MPI_Comm comm) const noexcept {
02074 int idx=comm-MPI_COMM_FIRST_CART;
02075 if (idx>=cartComm.size()) CkAbort("AMPI> Bad cartesian communicator used!\n");
02076 return *cartComm[idx];
02077 }
02078 inline bool isGraph(MPI_Comm comm) const noexcept {
02079 return (comm>=MPI_COMM_FIRST_GRAPH && comm<MPI_COMM_FIRST_DIST_GRAPH);
02080 }
02081 ampiCommStruct &getGraph(MPI_Comm comm) const noexcept {
02082 int idx=comm-MPI_COMM_FIRST_GRAPH;
02083 if (idx>=graphComm.size()) CkAbort("AMPI> Bad graph communicator used!\n");
02084 return *graphComm[idx];
02085 }
02086 inline bool isDistGraph(MPI_Comm comm) const noexcept {
02087 return (comm >= MPI_COMM_FIRST_DIST_GRAPH && comm < MPI_COMM_FIRST_INTER);
02088 }
02089 ampiCommStruct &getDistGraph(MPI_Comm comm) const noexcept {
02090 int idx = comm-MPI_COMM_FIRST_DIST_GRAPH;
02091 if (idx>=distGraphComm.size()) CkAbort("Bad distributed graph communicator used");
02092 return *distGraphComm[idx];
02093 }
02094 inline bool isInter(MPI_Comm comm) const noexcept {
02095 return (comm>=MPI_COMM_FIRST_INTER && comm<MPI_COMM_FIRST_INTRA);
02096 }
02097 const ampiCommStruct &getInter(MPI_Comm comm) const noexcept {
02098 int idx=comm-MPI_COMM_FIRST_INTER;
02099 if (idx>=interComm.size()) CkAbort("AMPI> Bad inter-communicator used!\n");
02100 return *interComm[idx];
02101 }
02102 inline bool isIntra(MPI_Comm comm) const noexcept {
02103 return (comm>=MPI_COMM_FIRST_INTRA && comm<MPI_COMM_FIRST_RESVD);
02104 }
02105 const ampiCommStruct &getIntra(MPI_Comm comm) const noexcept {
02106 int idx=comm-MPI_COMM_FIRST_INTRA;
02107 if (idx>=intraComm.size()) CkAbort("Bad intra-communicator used");
02108 return *intraComm[idx];
02109 }
02110
02111 void pup(PUP::er &p) noexcept;
02112
02113 void startCheckpoint(const char* dname) noexcept;
02114 void Checkpoint(int len, const char* dname) noexcept;
02115 void ResumeThread() noexcept;
02116 TCharm* getTCharmThread() const noexcept {return thread;}
02117 inline ampiParent* blockOnRecv() noexcept;
02118 inline CkDDT* getDDT() noexcept { return &myDDT; }
02119
02120 #if CMK_LBDB_ON
02121 void setMigratable(bool mig) noexcept {
02122 thread->setMigratable(mig);
02123 }
02124 #endif
02125
02126 const ampiCommStruct &getWorldStruct() const noexcept;
02127
02128 inline const ampiCommStruct &comm2CommStruct(MPI_Comm comm) const noexcept {
02129 if (comm==MPI_COMM_WORLD) return getWorldStruct();
02130 if (comm==worldNo) return getWorldStruct();
02131 if (isSplit(comm)) return getSplit(comm);
02132 if (isGroup(comm)) return getGroup(comm);
02133 if (isCart(comm)) return getCart(comm);
02134 if (isGraph(comm)) return getGraph(comm);
02135 if (isDistGraph(comm)) return getDistGraph(comm);
02136 if (isInter(comm)) return getInter(comm);
02137 if (isIntra(comm)) return getIntra(comm);
02138 return universeComm2CommStruct(comm);
02139 }
02140
02141 inline vector<int>& getKeyvals(MPI_Comm comm) noexcept {
02142 ampiCommStruct &cs = *(ampiCommStruct *)&comm2CommStruct(comm);
02143 return cs.getKeyvals();
02144 }
02145
02146 inline ampi *comm2ampi(MPI_Comm comm) const noexcept {
02147 if (comm==MPI_COMM_WORLD) return worldPtr;
02148 if (comm==worldNo) return worldPtr;
02149 if (isSplit(comm)) {
02150 const ampiCommStruct &st=getSplit(comm);
02151 return st.getProxy()[thisIndex].ckLocal();
02152 }
02153 if (isGroup(comm)) {
02154 const ampiCommStruct &st=getGroup(comm);
02155 return st.getProxy()[thisIndex].ckLocal();
02156 }
02157 if (isCart(comm)) {
02158 const ampiCommStruct &st = getCart(comm);
02159 return st.getProxy()[thisIndex].ckLocal();
02160 }
02161 if (isGraph(comm)) {
02162 const ampiCommStruct &st = getGraph(comm);
02163 return st.getProxy()[thisIndex].ckLocal();
02164 }
02165 if (isDistGraph(comm)) {
02166 const ampiCommStruct &st = getDistGraph(comm);
02167 return st.getProxy()[thisIndex].ckLocal();
02168 }
02169 if (isInter(comm)) {
02170 const ampiCommStruct &st=getInter(comm);
02171 return st.getProxy()[thisIndex].ckLocal();
02172 }
02173 if (isIntra(comm)) {
02174 const ampiCommStruct &st=getIntra(comm);
02175 return st.getProxy()[thisIndex].ckLocal();
02176 }
02177 if (comm>MPI_COMM_WORLD) return worldPtr;
02178 CkAbort("Invalid communicator used!");
02179 return NULL;
02180 }
02181
02182 inline bool hasComm(const MPI_Group group) const noexcept {
02183 MPI_Comm comm = (MPI_Comm)group;
02184 return ( comm==MPI_COMM_WORLD || comm==worldNo || isSplit(comm) || isGroup(comm) ||
02185 isCart(comm) || isGraph(comm) || isDistGraph(comm) || isIntra(comm) );
02186
02187 }
02188 inline vector<int> group2vec(MPI_Group group) const noexcept {
02189 if (group == MPI_GROUP_NULL || group == MPI_GROUP_EMPTY) {
02190 return vector<int>();
02191 }
02192 else if (hasComm(group)) {
02193 return comm2CommStruct((MPI_Comm)group).getIndices();
02194 }
02195 else {
02196 CkAssert(isInGroups(group));
02197 return groups[group]->getRanks();
02198 }
02199 }
02200 inline MPI_Group saveGroupStruct(const vector<int>& vec) noexcept {
02201 if (vec.empty()) return MPI_GROUP_EMPTY;
02202 int idx = groups.size();
02203 groups.resize(idx+1);
02204 groups[idx]=new groupStruct(vec);
02205 return (MPI_Group)idx;
02206 }
02207 inline int getRank(const MPI_Group group) const noexcept {
02208 vector<int> vec = group2vec(group);
02209 return getPosOp(thisIndex,vec);
02210 }
02211 inline AmpiRequestList &getReqs() noexcept { return ampiReqs; }
02212 inline int getMyPe() const noexcept {
02213 return CkMyPe();
02214 }
02215 inline bool hasWorld() const noexcept {
02216 return worldPtr!=NULL;
02217 }
02218
02219 inline void checkComm(MPI_Comm comm) const noexcept {
02220 if ((comm != MPI_COMM_SELF && comm != MPI_COMM_WORLD)
02221 || (isSplit(comm) && comm-MPI_COMM_FIRST_SPLIT >= splitComm.size())
02222 || (isGroup(comm) && comm-MPI_COMM_FIRST_GROUP >= groupComm.size())
02223 || (isCart(comm) && comm-MPI_COMM_FIRST_CART >= cartComm.size())
02224 || (isGraph(comm) && comm-MPI_COMM_FIRST_GRAPH >= graphComm.size())
02225 || (isDistGraph(comm) && comm-MPI_COMM_FIRST_DIST_GRAPH >= distGraphComm.size())
02226 || (isInter(comm) && comm-MPI_COMM_FIRST_INTER >= interComm.size())
02227 || (isIntra(comm) && comm-MPI_COMM_FIRST_INTRA >= intraComm.size()) )
02228 CkAbort("Invalid MPI_Comm\n");
02229 }
02230
02232 inline MPI_Group comm2group(const MPI_Comm comm) const noexcept {
02233 if(isInter(comm)) return MPI_GROUP_NULL;
02234 ampiCommStruct s = comm2CommStruct(comm);
02235 if(comm!=MPI_COMM_WORLD && comm!=s.getComm()) CkAbort("Error in ampiParent::comm2group()");
02236 return (MPI_Group)(s.getComm());
02237 }
02238
02239 inline int getRemoteSize(const MPI_Comm comm) const noexcept {
02240 if(isInter(comm)) return getInter(comm).getRemoteIndices().size();
02241 else return -1;
02242 }
02243 inline MPI_Group getRemoteGroup(const MPI_Comm comm) noexcept {
02244 if(isInter(comm)) return saveGroupStruct(getInter(comm).getRemoteIndices());
02245 else return MPI_GROUP_NULL;
02246 }
02247
02248 int createKeyval(MPI_Copy_function *copy_fn, MPI_Delete_function *delete_fn,
02249 int *keyval, void* extra_state) noexcept;
02250 bool getBuiltinKeyval(int keyval, void *attribute_val) noexcept;
02251 int setUserKeyval(MPI_Comm comm, int keyval, void *attribute_val) noexcept;
02252 bool getUserKeyval(MPI_Comm comm, vector<int>& keyvals, int keyval, void *attribute_val, int *flag) noexcept;
02253 int dupUserKeyvals(MPI_Comm old_comm, MPI_Comm new_comm) noexcept;
02254 int freeUserKeyval(int context, vector<int>& keyvals, int *keyval) noexcept;
02255 int freeUserKeyvals(int context, vector<int>& keyvals) noexcept;
02256
02257 int setAttr(MPI_Comm comm, vector<int>& keyvals, int keyval, void *attribute_val) noexcept;
02258 int getAttr(MPI_Comm comm, vector<int>& keyvals, int keyval, void *attribute_val, int *flag) noexcept;
02259 int deleteAttr(MPI_Comm comm, vector<int>& keyvals, int keyval) noexcept;
02260
02261 int addWinStruct(WinStruct *win) noexcept;
02262 WinStruct *getWinStruct(MPI_Win win) const noexcept;
02263 void removeWinStruct(WinStruct *win) noexcept;
02264
02265 int createInfo(MPI_Info *newinfo) noexcept;
02266 int dupInfo(MPI_Info info, MPI_Info *newinfo) noexcept;
02267 int setInfo(MPI_Info info, const char *key, const char *value) noexcept;
02268 int deleteInfo(MPI_Info info, const char *key) noexcept;
02269 int getInfo(MPI_Info info, const char *key, int valuelen, char *value, int *flag) const noexcept;
02270 int getInfoValuelen(MPI_Info info, const char *key, int *valuelen, int *flag) const noexcept;
02271 int getInfoNkeys(MPI_Info info, int *nkeys) const noexcept;
02272 int getInfoNthkey(MPI_Info info, int n, char *key) const noexcept;
02273 int freeInfo(MPI_Info info) noexcept;
02274 void defineInfoEnv(int nRanks_) noexcept;
02275 void defineInfoMigration() noexcept;
02276
02277
02278
02279
02280
02281 inline int createOp(MPI_User_function *fn, bool isCommutative) noexcept {
02282
02283 for (int i=0; i<userOps.size(); i++) {
02284 if (userOps[i].isFree()) {
02285 userOps[i].init(fn, isCommutative);
02286 return AMPI_MAX_PREDEFINED_OP + 1 + i;
02287 }
02288 }
02289
02290 userOps.emplace_back(fn, isCommutative);
02291 return AMPI_MAX_PREDEFINED_OP + userOps.size();
02292 }
02293 inline void freeOp(MPI_Op op) noexcept {
02294
02295 if (!opIsPredefined(op)) {
02296
02297 int opIdx = op - 1 - AMPI_MAX_PREDEFINED_OP;
02298 CkAssert(opIdx < userOps.size());
02299 userOps[opIdx].free();
02300 while (!userOps.empty() && userOps.back().isFree()) {
02301 userOps.pop_back();
02302 }
02303 }
02304 }
02305 inline bool opIsPredefined(MPI_Op op) const noexcept {
02306 return (op <= AMPI_MAX_PREDEFINED_OP);
02307 }
02308 inline bool opIsCommutative(MPI_Op op) const noexcept {
02309 if (opIsPredefined(op)) {
02310 return true;
02311 }
02312 else {
02313 int opIdx = op - 1 - AMPI_MAX_PREDEFINED_OP;
02314 CkAssert(opIdx < userOps.size());
02315 return userOps[opIdx].isCommutative;
02316 }
02317 }
02318 inline MPI_User_function* op2User_function(MPI_Op op) const noexcept {
02319 if (opIsPredefined(op)) {
02320 return predefinedOps[op];
02321 }
02322 else {
02323 int opIdx = op - 1 - AMPI_MAX_PREDEFINED_OP;
02324 CkAssert(opIdx < userOps.size());
02325 return userOps[opIdx].func;
02326 }
02327 }
02328 inline AmpiOpHeader op2AmpiOpHeader(MPI_Op op, MPI_Datatype type, int count) const noexcept {
02329 if (opIsPredefined(op)) {
02330 int size = myDDT.getType(type)->getSize(count);
02331 return AmpiOpHeader(predefinedOps[op], type, count, size);
02332 }
02333 else {
02334 int opIdx = op - 1 - AMPI_MAX_PREDEFINED_OP;
02335 CkAssert(opIdx < userOps.size());
02336 int size = myDDT.getType(type)->getSize(count);
02337 return AmpiOpHeader(userOps[opIdx].func, type, count, size);
02338 }
02339 }
02340 inline void applyOp(MPI_Datatype datatype, MPI_Op op, int count, const void* invec, void* inoutvec) const noexcept {
02341
02342 MPI_User_function *func = op2User_function(op);
02343 (func)((void*)invec, inoutvec, &count, &datatype);
02344 }
02345
02346 void init() noexcept;
02347 void finalize() noexcept;
02348 void block() noexcept;
02349 void yield() noexcept;
02350
02351 #if AMPI_PRINT_MSG_SIZES
02352
02353
02354 std::unordered_map<std::string, std::map<int, int> > msgSizes;
02355 inline bool isRankRecordingMsgSizes() noexcept;
02356 inline void recordMsgSize(const char* func, int msgSize) noexcept;
02357 void printMsgSizes() noexcept;
02358 #endif
02359
02360 #if AMPIMSGLOG
02361
02362 int pupBytes;
02363 #if CMK_USE_ZLIB && 0
02364 gzFile fMsgLog;
02365 PUP::tozDisk *toPUPer;
02366 PUP::fromzDisk *fromPUPer;
02367 #else
02368 FILE* fMsgLog;
02369 PUP::toDisk *toPUPer;
02370 PUP::fromDisk *fromPUPer;
02371 #endif
02372 #endif
02373 };
02374
02375
02376 class greq_class_desc {
02377 public:
02378 MPI_Grequest_query_function *query_fn;
02379 MPI_Grequest_free_function *free_fn;
02380 MPI_Grequest_cancel_function *cancel_fn;
02381 MPIX_Grequest_poll_function *poll_fn;
02382 MPIX_Grequest_wait_function *wait_fn;
02383
02384 void pup(PUP::er &p) noexcept {
02385 p((char *)query_fn, sizeof(void *));
02386 p((char *)free_fn, sizeof(void *));
02387 p((char *)cancel_fn, sizeof(void *));
02388 p((char *)poll_fn, sizeof(void *));
02389 p((char *)wait_fn, sizeof(void *));
02390 }
02391 };
02392
02393
02394
02395
02396
02397 class ampi final : public CBase_ampi {
02398 private:
02399 friend class IReq;
02400 friend class SendReq;
02401 friend class SsendReq;
02402 friend class RednReq;
02403 friend class GatherReq;
02404 friend class GathervReq;
02405
02406 ampiParent *parent;
02407 CProxy_ampiParent parentProxy;
02408 TCharm *thread;
02409 int myRank;
02410 AmpiSeqQ oorder;
02411
02412 public:
02413
02414
02415
02416
02417 Amm<AmpiRequest *, AMPI_AMM_PT2PT_POOL_SIZE> postedReqs;
02418 Amm<AmpiMsg *, AMPI_AMM_PT2PT_POOL_SIZE> unexpectedMsgs;
02419
02420
02421
02422 Amm<AmpiRequest *, AMPI_AMM_COLL_POOL_SIZE> postedBcastReqs;
02423 Amm<AmpiMsg *, AMPI_AMM_COLL_POOL_SIZE> unexpectedBcastMsgs;
02424
02425
02426 vector<greq_class_desc> greq_classes;
02427
02428 private:
02429 ampiCommStruct myComm;
02430 vector<int> tmpVec;
02431 CProxy_ampi remoteProxy;
02432 CkPupPtrVec<win_obj> winObjects;
02433
02434 private:
02435 void inorder(AmpiMsg *msg) noexcept;
02436 void inorderBcast(AmpiMsg *msg, bool deleteMsg) noexcept;
02437 void inorderRdma(char* buf, int size, CMK_REFNUM_TYPE seq, int tag, int srcRank,
02438 MPI_Comm comm, int ssendReq) noexcept;
02439
02440 void init() noexcept;
02441 void findParent(bool forMigration) noexcept;
02442
02443 public:
02444 ampi() noexcept;
02445 ampi(CkArrayID parent_,const ampiCommStruct &s) noexcept;
02446 ampi(CkMigrateMessage *msg) noexcept;
02447 void ckJustMigrated() noexcept;
02448 void ckJustRestored() noexcept;
02449 ~ampi() noexcept;
02450
02451 void pup(PUP::er &p) noexcept;
02452
02453 void allInitDone() noexcept;
02454 void setInitDoneFlag() noexcept;
02455
02456 void unblock() noexcept;
02457 void injectMsg(int size, char* buf) noexcept;
02458 void generic(AmpiMsg *) noexcept;
02459 void genericRdma(char* buf, int size, CMK_REFNUM_TYPE seq, int tag, int srcRank,
02460 MPI_Comm destcomm, int ssendReq) noexcept;
02461 void completedRdmaSend(CkDataMsg *msg) noexcept;
02462 void ssend_ack(int sreq) noexcept;
02463 void barrierResult() noexcept;
02464 void ibarrierResult() noexcept;
02465 void bcastResult(AmpiMsg *msg) noexcept;
02466 void rednResult(CkReductionMsg *msg) noexcept;
02467 void irednResult(CkReductionMsg *msg) noexcept;
02468
02469 void splitPhase1(CkReductionMsg *msg) noexcept;
02470 void splitPhaseInter(CkReductionMsg *msg) noexcept;
02471 void commCreatePhase1(MPI_Comm nextGroupComm) noexcept;
02472 void intercommCreatePhase1(MPI_Comm nextInterComm) noexcept;
02473 void intercommMergePhase1(MPI_Comm nextIntraComm) noexcept;
02474
02475 private:
02476 CProxy_ampi createNewChildAmpiSync() noexcept;
02477 void insertNewChildAmpiElements(MPI_Comm newComm, CProxy_ampi newAmpi) noexcept;
02478
02479 inline void handleBlockedReq(AmpiRequest* req) noexcept {
02480 if (req->isBlocked() && parent->numBlockedReqs != 0) {
02481 parent->numBlockedReqs--;
02482 }
02483 }
02484 inline void resumeThreadIfReady() noexcept {
02485 if (parent->resumeOnRecv && parent->numBlockedReqs == 0) {
02486 thread->resume();
02487 }
02488 }
02489
02490 public:
02491 inline const ampiCommStruct &comm2CommStruct(MPI_Comm comm) const noexcept {
02492 return parent->comm2CommStruct(comm);
02493 }
02494 inline const ampiCommStruct &getCommStruct() const noexcept { return myComm; }
02495
02496 inline ampi* blockOnRecv() noexcept;
02497 inline ampi* blockOnColl() noexcept;
02498 inline void setBlockingReq(AmpiRequest *req) noexcept;
02499 MPI_Request postReq(AmpiRequest* newreq) noexcept;
02500
02501 inline CMK_REFNUM_TYPE getSeqNo(int destRank, MPI_Comm destcomm, int tag) noexcept;
02502 AmpiMsg *makeBcastMsg(const void *buf,int count,MPI_Datatype type,int root,MPI_Comm destcomm) noexcept;
02503 AmpiMsg *makeAmpiMsg(int destRank,int t,int sRank,const void *buf,int count,
02504 MPI_Datatype type,MPI_Comm destcomm, int ssendReq=0) noexcept;
02505
02506 MPI_Request send(int t, int s, const void* buf, int count, MPI_Datatype type, int rank,
02507 MPI_Comm destcomm, int ssendReq=0, AmpiSendType sendType=BLOCKING_SEND) noexcept;
02508 static void sendraw(int t, int s, void* buf, int len, CkArrayID aid, int idx) noexcept;
02509 inline MPI_Request sendLocalMsg(int t, int sRank, const void* buf, int size, MPI_Datatype type, int destRank,
02510 MPI_Comm destcomm, ampi* destPtr, int ssendReq, AmpiSendType sendType) noexcept;
02511 inline MPI_Request sendRdmaMsg(int t, int sRank, const void* buf, int size, MPI_Datatype type, int destIdx,
02512 int destRank, MPI_Comm destcomm, CProxy_ampi arrProxy, int ssendReq) noexcept;
02513 inline bool destLikelyWithinProcess(CProxy_ampi arrProxy, int destIdx) const noexcept {
02514 CkArray* localBranch = arrProxy.ckLocalBranch();
02515 int destPe = localBranch->lastKnown(CkArrayIndex1D(destIdx));
02516 return (CkNodeOf(destPe) == CkMyNode());
02517 }
02518 MPI_Request delesend(int t, int s, const void* buf, int count, MPI_Datatype type, int rank,
02519 MPI_Comm destcomm, CProxy_ampi arrproxy, int ssend, AmpiSendType sendType) noexcept;
02520 inline void processAmpiMsg(AmpiMsg *msg, void* buf, MPI_Datatype type, int count) noexcept;
02521 inline void processRdmaMsg(const void *sbuf, int slength, int ssendReq, int srank, void* rbuf,
02522 int rcount, MPI_Datatype rtype, MPI_Comm comm) noexcept;
02523 inline void processRednMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int count) noexcept;
02524 inline void processNoncommutativeRednMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int count,
02525 MPI_User_function* func) noexcept;
02526 inline void processGatherMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int recvCount) noexcept;
02527 inline void processGathervMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type,
02528 int* recvCounts, int* displs) noexcept;
02529 inline AmpiMsg * getMessage(int t, int s, MPI_Comm comm, int *sts) const noexcept;
02530 int recv(int t,int s,void* buf,int count,MPI_Datatype type,MPI_Comm comm,MPI_Status *sts=NULL) noexcept;
02531 void irecv(void *buf, int count, MPI_Datatype type, int src,
02532 int tag, MPI_Comm comm, MPI_Request *request) noexcept;
02533 void mrecv(int tag, int src, void* buf, int count, MPI_Datatype datatype, MPI_Comm comm,
02534 MPI_Status* status, MPI_Message* message) noexcept;
02535 void imrecv(void* buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm,
02536 MPI_Request* request, MPI_Message* message) noexcept;
02537 void irecvBcast(void *buf, int count, MPI_Datatype type, int src,
02538 MPI_Comm comm, MPI_Request *request) noexcept;
02539 void sendrecv(const void *sbuf, int scount, MPI_Datatype stype, int dest, int stag,
02540 void *rbuf, int rcount, MPI_Datatype rtype, int src, int rtag,
02541 MPI_Comm comm, MPI_Status *sts) noexcept;
02542 void sendrecv_replace(void* buf, int count, MPI_Datatype datatype,
02543 int dest, int sendtag, int source, int recvtag,
02544 MPI_Comm comm, MPI_Status *status) noexcept;
02545 void probe(int t,int s,MPI_Comm comm,MPI_Status *sts) noexcept;
02546 void mprobe(int t, int s, MPI_Comm comm, MPI_Status *sts, MPI_Message *message) noexcept;
02547 int iprobe(int t,int s,MPI_Comm comm,MPI_Status *sts) noexcept;
02548 int improbe(int t, int s, MPI_Comm comm, MPI_Status *sts, MPI_Message *message) noexcept;
02549 void barrier() noexcept;
02550 void ibarrier(MPI_Request *request) noexcept;
02551 void bcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm comm) noexcept;
02552 int intercomm_bcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm intercomm) noexcept;
02553 void ibcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm comm, MPI_Request* request) noexcept;
02554 int intercomm_ibcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm intercomm, MPI_Request *request) noexcept;
02555 static void bcastraw(void* buf, int len, CkArrayID aid) noexcept;
02556 void split(int color,int key,MPI_Comm *dest, int type) noexcept;
02557 void commCreate(const vector<int>& vec,MPI_Comm *newcomm) noexcept;
02558 MPI_Comm cartCreate0D() noexcept;
02559 MPI_Comm cartCreate(vector<int>& vec, int ndims, const int* dims) noexcept;
02560 void graphCreate(const vector<int>& vec, MPI_Comm *newcomm) noexcept;
02561 void distGraphCreate(const vector<int>& vec, MPI_Comm *newcomm) noexcept;
02562 void intercommCreate(const vector<int>& rvec, int root, MPI_Comm tcomm, MPI_Comm *ncomm) noexcept;
02563
02564 inline bool isInter() const noexcept { return myComm.isinter(); }
02565 void intercommMerge(int first, MPI_Comm *ncomm) noexcept;
02566
02567 inline int getWorldRank() const noexcept {return parent->thisIndex;}
02569 inline int getRank() const noexcept {return myRank;}
02570 inline int getSize() const noexcept {return myComm.getSize();}
02571 inline MPI_Comm getComm() const noexcept {return myComm.getComm();}
02572 inline void setCommName(const char *name) noexcept {myComm.setName(name);}
02573 inline void getCommName(char *name, int *len) const noexcept {myComm.getName(name,len);}
02574 inline vector<int> getIndices() const noexcept { return myComm.getIndices(); }
02575 inline vector<int> getRemoteIndices() const noexcept { return myComm.getRemoteIndices(); }
02576 inline const CProxy_ampi &getProxy() const noexcept {return thisProxy;}
02577 inline const CProxy_ampi &getRemoteProxy() const noexcept {return remoteProxy;}
02578 inline void setRemoteProxy(CProxy_ampi rproxy) noexcept { remoteProxy = rproxy; thread->resume(); }
02579 inline int getIndexForRank(int r) const noexcept {return myComm.getIndexForRank(r);}
02580 inline int getIndexForRemoteRank(int r) const noexcept {return myComm.getIndexForRemoteRank(r);}
02581 void findNeighbors(MPI_Comm comm, int rank, vector<int>& neighbors) const noexcept;
02582 inline const vector<int>& getNeighbors() const noexcept { return myComm.getTopologyforNeighbors()->getnbors(); }
02583 inline bool opIsCommutative(MPI_Op op) const noexcept { return parent->opIsCommutative(op); }
02584 inline MPI_User_function* op2User_function(MPI_Op op) const noexcept { return parent->op2User_function(op); }
02585 void topoDup(int topoType, int rank, MPI_Comm comm, MPI_Comm *newcomm) noexcept;
02586
02587 inline AmpiRequestList& getReqs() noexcept { return parent->ampiReqs; }
02588 CkDDT *getDDT() noexcept {return &parent->myDDT;}
02589 CthThread getThread() const noexcept { return thread->getThread(); }
02590
02591 public:
02592 MPI_Win createWinInstance(void *base, MPI_Aint size, int disp_unit, MPI_Info info) noexcept;
02593 int deleteWinInstance(MPI_Win win) noexcept;
02594 int winGetGroup(WinStruct *win, MPI_Group *group) const noexcept;
02595 int winPut(const void *orgaddr, int orgcnt, MPI_Datatype orgtype, int rank,
02596 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, WinStruct *win) noexcept;
02597 int winGet(void *orgaddr, int orgcnt, MPI_Datatype orgtype, int rank,
02598 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, WinStruct *win) noexcept;
02599 int winIget(MPI_Aint orgdisp, int orgcnt, MPI_Datatype orgtype, int rank,
02600 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, WinStruct *win,
02601 MPI_Request *req) noexcept;
02602 int winIgetWait(MPI_Request *request, MPI_Status *status) noexcept;
02603 int winIgetFree(MPI_Request *request, MPI_Status *status) noexcept;
02604 void winRemotePut(int orgtotalsize, char* orgaddr, int orgcnt, MPI_Datatype orgtype,
02605 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, int winIndex) noexcept;
02606 char* winLocalGet(int orgcnt, MPI_Datatype orgtype, MPI_Aint targdisp, int targcnt,
02607 MPI_Datatype targtype, int winIndex) noexcept;
02608 AmpiMsg* winRemoteGet(int orgcnt, MPI_Datatype orgtype, MPI_Aint targdisp,
02609 int targcnt, MPI_Datatype targtype, int winIndex) noexcept;
02610 AmpiMsg* winRemoteIget(MPI_Aint orgdisp, int orgcnt, MPI_Datatype orgtype, MPI_Aint targdisp,
02611 int targcnt, MPI_Datatype targtype, int winIndex) noexcept;
02612 int winLock(int lock_type, int rank, WinStruct *win) noexcept;
02613 int winUnlock(int rank, WinStruct *win) noexcept;
02614 void winRemoteLock(int lock_type, int winIndex, int requestRank) noexcept;
02615 void winRemoteUnlock(int winIndex, int requestRank) noexcept;
02616 int winAccumulate(const void *orgaddr, int orgcnt, MPI_Datatype orgtype, int rank,
02617 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype,
02618 MPI_Op op, WinStruct *win) noexcept;
02619 void winRemoteAccumulate(int orgtotalsize, char* orgaddr, int orgcnt, MPI_Datatype orgtype,
02620 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype,
02621 MPI_Op op, int winIndex) noexcept;
02622 int winGetAccumulate(const void *orgaddr, int orgcnt, MPI_Datatype orgtype, void *resaddr,
02623 int rescnt, MPI_Datatype restype, int rank, MPI_Aint targdisp,
02624 int targcnt, MPI_Datatype targtype, MPI_Op op, WinStruct *win) noexcept;
02625 void winLocalGetAccumulate(int orgtotalsize, char* sorgaddr, int orgcnt, MPI_Datatype orgtype,
02626 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, MPI_Op op,
02627 char *resaddr, int winIndex) noexcept;
02628 AmpiMsg* winRemoteGetAccumulate(int orgtotalsize, char* sorgaddr, int orgcnt, MPI_Datatype orgtype,
02629 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, MPI_Op op,
02630 int winIndex) noexcept;
02631 int winCompareAndSwap(const void *orgaddr, const void *compaddr, void *resaddr, MPI_Datatype type,
02632 int rank, MPI_Aint targdisp, WinStruct *win) noexcept;
02633 char* winLocalCompareAndSwap(int size, char* sorgaddr, char* compaddr, MPI_Datatype type,
02634 MPI_Aint targdisp, int winIndex) noexcept;
02635 AmpiMsg* winRemoteCompareAndSwap(int size, char *sorgaddr, char *compaddr, MPI_Datatype type,
02636 MPI_Aint targdisp, int winIndex) noexcept;
02637 void winSetName(WinStruct *win, const char *name) noexcept;
02638 void winGetName(WinStruct *win, char *name, int *length) const noexcept;
02639 win_obj* getWinObjInstance(WinStruct *win) const noexcept;
02640 int getNewSemaId() noexcept;
02641
02642 int intercomm_scatter(int root, const void *sendbuf, int sendcount, MPI_Datatype sendtype,
02643 void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm intercomm) noexcept;
02644 int intercomm_iscatter(int root, const void *sendbuf, int sendcount, MPI_Datatype sendtype,
02645 void *recvbuf, int recvcount, MPI_Datatype recvtype,
02646 MPI_Comm intercomm, MPI_Request *request) noexcept;
02647 int intercomm_scatterv(int root, const void* sendbuf, const int* sendcounts, const int* displs,
02648 MPI_Datatype sendtype, void* recvbuf, int recvcount,
02649 MPI_Datatype recvtype, MPI_Comm intercomm) noexcept;
02650 int intercomm_iscatterv(int root, const void* sendbuf, const int* sendcounts, const int* displs,
02651 MPI_Datatype sendtype, void* recvbuf, int recvcount,
02652 MPI_Datatype recvtype, MPI_Comm intercomm, MPI_Request* request) noexcept;
02653 };
02654
02655 ampiParent *getAmpiParent() noexcept;
02656 bool isAmpiThread() noexcept;
02657 ampi *getAmpiInstance(MPI_Comm comm) noexcept;
02658 void checkComm(MPI_Comm comm) noexcept;
02659 void checkRequest(MPI_Request req) noexcept;
02660 void handle_MPI_BOTTOM(void* &buf, MPI_Datatype type) noexcept;
02661 void handle_MPI_BOTTOM(void* &buf1, MPI_Datatype type1, void* &buf2, MPI_Datatype type2) noexcept;
02662
02663 #if AMPI_ERROR_CHECKING
02664 int ampiErrhandler(const char* func, int errcode) noexcept;
02665 #else
02666 #define ampiErrhandler(func, errcode) (errcode)
02667 #endif
02668
02669
02670 #if CMK_TRACE_ENABLED
02671
02672
02673 static const char *funclist[] = {"AMPI_Abort", "AMPI_Add_error_class", "AMPI_Add_error_code", "AMPI_Add_error_string",
02674 "AMPI_Address", "AMPI_Allgather", "AMPI_Allgatherv", "AMPI_Allreduce", "AMPI_Alltoall",
02675 "AMPI_Alltoallv", "AMPI_Alltoallw", "AMPI_Attr_delete", "AMPI_Attr_get",
02676 "AMPI_Attr_put", "AMPI_Barrier", "AMPI_Bcast", "AMPI_Bsend", "AMPI_Cancel",
02677 "AMPI_Cart_coords", "AMPI_Cart_create", "AMPI_Cart_get", "AMPI_Cart_map",
02678 "AMPI_Cart_rank", "AMPI_Cart_shift", "AMPI_Cart_sub", "AMPI_Cartdim_get",
02679 "AMPI_Comm_call_errhandler", "AMPI_Comm_compare", "AMPI_Comm_create", "AMPI_Comm_create_group",
02680 "AMPI_Comm_create_errhandler", "AMPI_Comm_create_keyval", "AMPI_Comm_delete_attr",
02681 "AMPI_Comm_dup", "AMPI_Comm_dup_with_info", "AMPI_Comm_free",
02682 "AMPI_Comm_free_errhandler", "AMPI_Comm_free_keyval", "AMPI_Comm_get_attr",
02683 "AMPI_Comm_get_errhandler", "AMPI_Comm_get_info", "AMPI_Comm_get_name",
02684 "AMPI_Comm_group", "AMPI_Comm_rank", "AMPI_Comm_remote_group", "AMPI_Comm_remote_size",
02685 "AMPI_Comm_set_attr", "AMPI_Comm_set_errhandler", "AMPI_Comm_set_info", "AMPI_Comm_set_name",
02686 "AMPI_Comm_size", "AMPI_Comm_split", "AMPI_Comm_split_type", "AMPI_Comm_test_inter",
02687 "AMPI_Dims_create", "AMPI_Dist_graph_create", "AMPI_Dist_graph_create_adjacent",
02688 "AMPI_Dist_graph_neighbors", "AMPI_Dist_graph_neighbors_count",
02689 "AMPI_Errhandler_create", "AMPI_Errhandler_free", "AMPI_Errhandler_get",
02690 "AMPI_Errhandler_set", "AMPI_Error_class", "AMPI_Error_string", "AMPI_Exscan", "AMPI_Finalize",
02691 "AMPI_Finalized", "AMPI_Gather", "AMPI_Gatherv", "AMPI_Get_address", "AMPI_Get_count",
02692 "AMPI_Get_elements", "AMPI_Get_library_version", "AMPI_Get_processor_name", "AMPI_Get_version",
02693 "AMPI_Graph_create", "AMPI_Graph_get", "AMPI_Graph_map", "AMPI_Graph_neighbors",
02694 "AMPI_Graph_neighbors_count", "AMPI_Graphdims_get", "AMPI_Group_compare", "AMPI_Group_difference",
02695 "AMPI_Group_excl", "AMPI_Group_free", "AMPI_Group_incl", "AMPI_Group_intersection",
02696 "AMPI_Group_range_excl", "AMPI_Group_range_incl", "AMPI_Group_rank", "AMPI_Group_size",
02697 "AMPI_Group_translate_ranks", "AMPI_Group_union", "AMPI_Iallgather", "AMPI_Iallgatherv",
02698 "AMPI_Iallreduce", "AMPI_Ialltoall", "AMPI_Ialltoallv", "AMPI_Ialltoallw", "AMPI_Ibarrier",
02699 "AMPI_Ibcast", "AMPI_Iexscan", "AMPI_Igather", "AMPI_Igatherv", "AMPI_Ineighbor_allgather",
02700 "AMPI_Ineighbor_allgatherv", "AMPI_Ineighbor_alltoall", "AMPI_Ineighbor_alltoallv",
02701 "AMPI_Ineighbor_alltoallw", "AMPI_Init", "AMPI_Init_thread", "AMPI_Initialized", "AMPI_Intercomm_create",
02702 "AMPI_Intercomm_merge", "AMPI_Iprobe", "AMPI_Irecv", "AMPI_Ireduce", "AMPI_Ireduce_scatter",
02703 "AMPI_Ireduce_scatter_block", "AMPI_Is_thread_main", "AMPI_Iscan", "AMPI_Iscatter", "AMPI_Iscatterv",
02704 "AMPI_Isend", "AMPI_Issend", "AMPI_Keyval_create", "AMPI_Keyval_free", "AMPI_Neighbor_allgather",
02705 "AMPI_Neighbor_allgatherv", "AMPI_Neighbor_alltoall", "AMPI_Neighbor_alltoallv", "AMPI_Neighbor_alltoallw",
02706 "AMPI_Op_commutative", "AMPI_Op_create", "AMPI_Op_free", "AMPI_Pack", "AMPI_Pack_size",
02707 "AMPI_Pcontrol", "AMPI_Probe", "AMPI_Query_thread", "AMPI_Recv", "AMPI_Recv_init", "AMPI_Reduce",
02708 "AMPI_Reduce_local", "AMPI_Reduce_scatter", "AMPI_Reduce_scatter_block", "AMPI_Request_free",
02709 "AMPI_Request_get_status", "AMPI_Rsend", "AMPI_Scan", "AMPI_Scatter", "AMPI_Scatterv", "AMPI_Send",
02710 "AMPI_Send_init", "AMPI_Sendrecv", "AMPI_Sendrecv_replace", "AMPI_Ssend", "AMPI_Ssend_init",
02711 "AMPI_Start", "AMPI_Startall", "AMPI_Status_set_cancelled", "AMPI_Status_set_elements", "AMPI_Test",
02712 "AMPI_Test_cancelled", "AMPI_Testall", "AMPI_Testany", "AMPI_Testsome", "AMPI_Topo_test",
02713 "AMPI_Type_commit", "AMPI_Type_contiguous", "AMPI_Type_create_hindexed",
02714 "AMPI_Type_create_hindexed_block", "AMPI_Type_create_hvector", "AMPI_Type_create_indexed_block",
02715 "AMPI_Type_create_keyval", "AMPI_Type_create_resized", "AMPI_Type_create_struct",
02716 "AMPI_Type_delete_attr", "AMPI_Type_dup", "AMPI_Type_extent", "AMPI_Type_free",
02717 "AMPI_Type_free_keyval", "AMPI_Type_get_attr", "AMPI_Type_get_contents", "AMPI_Type_get_envelope",
02718 "AMPI_Type_get_extent", "AMPI_Type_get_name", "AMPI_Type_get_true_extent", "AMPI_Type_hindexed",
02719 "AMPI_Type_hvector", "AMPI_Type_indexed", "AMPI_Type_lb", "AMPI_Type_set_attr",
02720 "AMPI_Type_set_name", "AMPI_Type_size", "AMPI_Type_struct", "AMPI_Type_ub", "AMPI_Type_vector",
02721 "AMPI_Type_create_darray", "AMPI_Type_create_subarray",
02722 "AMPI_Unpack", "AMPI_Wait", "AMPI_Waitall", "AMPI_Waitany", "AMPI_Waitsome", "AMPI_Wtick", "AMPI_Wtime",
02723 "AMPI_Accumulate", "AMPI_Compare_and_swap", "AMPI_Fetch_and_op", "AMPI_Get", "AMPI_Get_accumulate",
02724 "AMPI_Info_create", "AMPI_Info_delete", "AMPI_Info_dup", "AMPI_Info_free", "AMPI_Info_get",
02725 "AMPI_Info_get_nkeys", "AMPI_Info_get_nthkey", "AMPI_Info_get_valuelen",
02726 "AMPI_Info_set", "AMPI_Put", "AMPI_Raccumulate", "AMPI_Rget", "AMPI_Rget_accumulate",
02727 "AMPI_Rput", "AMPI_Win_complete", "AMPI_Win_create", "AMPI_Win_create_errhandler",
02728 "AMPI_Win_create_keyval", "AMPI_Win_delete_attr", "AMPI_Win_fence", "AMPI_Win_free",
02729 "AMPI_Win_free_keyval", "AMPI_Win_get_attr", "AMPI_Win_get_errhandler",
02730 "AMPI_Win_get_group", "AMPI_Win_get_info", "AMPI_Win_get_name", "AMPI_Win_lock",
02731 "AMPI_Win_post", "AMPI_Win_set_attr", "AMPI_Win_set_errhandler", "AMPI_Win_set_info",
02732 "AMPI_Win_set_name", "AMPI_Win_start", "AMPI_Win_test", "AMPI_Win_unlock",
02733 "AMPI_Win_wait", "AMPI_Exit" , "AMPI_Migrate",
02734 "AMPI_Load_start_measure", "AMPI_Load_stop_measure",
02735 "AMPI_Load_set_value", "AMPI_Migrate_to_pe", "AMPI_Set_migratable",
02736 "AMPI_Register_pup", "AMPI_Get_pup_data", "AMPI_Register_main",
02737 "AMPI_Register_about_to_migrate", "AMPI_Register_just_migrated",
02738 "AMPI_Iget", "AMPI_Iget_wait", "AMPI_Iget_free", "AMPI_Iget_data",
02739 "AMPI_Type_is_contiguous", "AMPI_Yield", "AMPI_Suspend",
02740 "AMPI_Resume", "AMPI_Print", "AMPI_Alltoall_medium",
02741 "AMPI_Alltoall_long", "AMPI_System"};
02742
02743
02744
02745 #endif // CMK_TRACE_ENABLED
02746
02747
02748 #if CMK_ERROR_CHECKING
02749 #define AMPI_API(routineName) \
02750 if (!isAmpiThread()) { CkAbort("AMPI> cannot call MPI routines from non-AMPI threads!"); } \
02751 TCHARM_API_TRACE(routineName, "ampi");
02752 #else
02753 #define AMPI_API(routineName) TCHARM_API_TRACE(routineName, "ampi")
02754 #endif
02755
02756
02757 #define AMPI_API_INIT(routineName) TCHARM_API_TRACE(routineName, "ampi")
02758
02759 #endif // _AMPIIMPL_H