00001
00013 #include "idxl.h"
00014 #include "charm-api.h"
00015
00016 void IDXL_Abort(const char *callingRoutine,const char *msg,int m0,int m1,int m2)
00017 {
00018 char msg1[1024], msg2[1536];
00019 sprintf(msg1,msg,m0,m1,m2);
00020 sprintf(msg2,"Fatal error in IDXL routine %s:\n%s",callingRoutine,msg1);
00021 CkAbort(msg2);
00022 }
00023
00024 CLINKAGE void pupIDXL_Chunk(pup_er cp) {
00025 PUP::er &p=*(PUP::er *)cp;
00026 IDXL_Chunk *c=(IDXL_Chunk *)TCHARM_Get_global(IDXL_globalID);
00027 if (c==NULL) {
00028 c=new IDXL_Chunk((CkMigrateMessage *)0);
00029 TCHARM_Set_global(IDXL_globalID,c,pupIDXL_Chunk);
00030 }
00031 c->pup(p);
00032 if (p.isDeleting()) {
00033 delete c;
00036 TCHARM_Set_global(IDXL_globalID,0,pupIDXL_Chunk);
00037 }
00038 }
00039 IDXL_Chunk *IDXL_Chunk::get(const char *callingRoutine) {
00040 IDXL_Chunk *c=getNULL();
00041 if(!c) IDXL_Abort(callingRoutine,"IDXL is not initialized");
00042 return c;
00043 }
00044
00045 CLINKAGE void
00046 IDXL_Init(int mpi_comm) {
00047 if (!TCHARM_Get_global(IDXL_globalID)) {
00048 IDXL_Chunk *c=new IDXL_Chunk(mpi_comm);
00049 TCHARM_Set_global(IDXL_globalID,c,pupIDXL_Chunk);
00050 }
00051 }
00052 FORTRAN_AS_C(IDXL_INIT,IDXL_Init,idxl_init, (int *comm), (*comm))
00053
00054 IDXL_Chunk::IDXL_Chunk(int mpi_comm_)
00055 :mpi_comm(mpi_comm_), currentComm(0)
00056 {
00057 init();
00058 }
00059 IDXL_Chunk::IDXL_Chunk(CkMigrateMessage *m) :currentComm(0)
00060 {
00061 init();
00062 }
00063 void IDXL_Chunk::init(void) {
00064
00065 }
00066
00067 void IDXL_Chunk::pup(PUP::er &p) {
00068 p|mpi_comm;
00069
00070 p|layouts;
00071 if (currentComm && !currentComm->isComplete()){
00072 CkPrintf("ERROR: Cannot migrate with ongoing IDXL communication: currentComm=%p ispacking=%d isunpacking=%d\n", currentComm, (int)p.isPacking(), (int)p.isUnpacking());
00073 CkAbort("Cannot migrate with ongoing IDXL communication");
00074 }
00075
00076
00077 int i, nDynamic=0;
00078 if (!p.isUnpacking())
00079 for (i=0;i<dynamic_idxls.size();i++)
00080 if (dynamic_idxls[i]) nDynamic++;
00081 p|nDynamic;
00082 if (p.isUnpacking()) {
00083 for (int d=0;d<nDynamic;d++)
00084 {
00085 p|i;
00086 dynamic_idxls[i]=new IDXL;
00087 p|*dynamic_idxls[i];
00088 }
00089 } else {
00090 for (i=0;i<dynamic_idxls.size();i++)
00091 if (dynamic_idxls[i]) {
00092 p|i;
00093 p|*dynamic_idxls[i];
00094 }
00095 }
00096 }
00097
00098 IDXL_Chunk::~IDXL_Chunk() {
00099
00100 for (int i=0;i<dynamic_idxls.size();i++)
00101 if (dynamic_idxls[i]) delete dynamic_idxls[i];
00102 delete currentComm;
00103 currentComm = 0;
00104 }
00105
00106
00108 IDXL_t IDXL_Chunk::addDynamic(void)
00109 {
00110 IDXL *ret=new IDXL;
00111 ret->allocateDual();
00112 return IDXL_DYNAMIC_IDXL_T+storeToFreeIndex(dynamic_idxls,ret);
00113 }
00115 IDXL_t IDXL_Chunk::addStatic(IDXL *idx,IDXL_t at) {
00116 if (at!=-1)
00117 {
00118 if (at<IDXL_STATIC_IDXL_T || at>=IDXL_LAST_IDXL_T)
00119 CkAbort("Provided bad fixed address to IDXL_Chunk::add!");
00120 int lat=at-IDXL_STATIC_IDXL_T;
00121 while (static_idxls.size()<=lat) static_idxls.push_back(NULL);
00122 if (static_idxls[lat]==NULL)
00123 {
00124 static_idxls[lat]=idx;
00125 return at;
00126 }
00127 else
00128 at=-1;
00129 }
00130 if (at==-1) {
00131 return IDXL_STATIC_IDXL_T+storeToFreeIndex(static_idxls,idx);
00132 }
00133 return -1;
00134 }
00135
00137 void IDXL_Chunk::check(IDXL_t at,const char *callingRoutine) const {
00138 if (at<IDXL_DYNAMIC_IDXL_T || at>=IDXL_LAST_IDXL_T)
00139 IDXL_Abort(callingRoutine,"Invalid IDXL_t %d",at);
00140 }
00141 IDXL &IDXL_Chunk::lookup(IDXL_t at,const char *callingRoutine) {
00142 IDXL *ret=0;
00143 if (at>=IDXL_DYNAMIC_IDXL_T && at<IDXL_DYNAMIC_IDXL_T+dynamic_idxls.size())
00144 ret=dynamic_idxls[at-IDXL_DYNAMIC_IDXL_T];
00145 else if (at>=IDXL_STATIC_IDXL_T && at<IDXL_STATIC_IDXL_T+static_idxls.size())
00146 ret=static_idxls[at-IDXL_STATIC_IDXL_T];
00147 if (ret==NULL)
00148 IDXL_Abort(callingRoutine,"Trying to look up invalid IDXL_t %d",at);
00149 return *ret;
00150 }
00151 const IDXL &IDXL_Chunk::lookup(IDXL_t at,const char *callingRoutine) const {
00152 IDXL_Chunk *dthis=(IDXL_Chunk *)this;
00153 return dthis->lookup(at,callingRoutine);
00154 }
00155 void IDXL_Chunk::destroy(IDXL_t at,const char *callingRoutine) {
00156 IDXL **ret=NULL;
00157 if (at>=IDXL_DYNAMIC_IDXL_T && at<IDXL_DYNAMIC_IDXL_T+dynamic_idxls.size())
00158 ret=&dynamic_idxls[at-IDXL_DYNAMIC_IDXL_T];
00159 else if (at>=IDXL_STATIC_IDXL_T && at<IDXL_STATIC_IDXL_T+static_idxls.size())
00160 ret=&static_idxls[at-IDXL_STATIC_IDXL_T];
00161 if (ret==NULL)
00162 IDXL_Abort(callingRoutine,"Trying to destroy invalid IDXL_t %d",at);
00163 if (*ret==NULL)
00164 IDXL_Abort(callingRoutine,"Trying to destroy already deleted IDXL_t %d",at);
00165 if (at<IDXL_STATIC_IDXL_T)
00166 delete *ret;
00167 *ret=NULL;
00168 }
00169
00170
00171
00173 IDXL_Layout_List &IDXL_Layout_List::get(void)
00174 {
00175 return IDXL_Chunk::get("IDXL_Layouts::get")->layouts;
00176 }
00177
00178
00179
00180 IDXL_Comm_t IDXL_Chunk::addComm(int tag,int context)
00181 {
00182 if (currentComm && !currentComm->isComplete()) CkAbort("Cannot start two IDXL_Comms at once");
00183 if (context==0) context=mpi_comm;
00184 if (currentComm==0)
00185 currentComm=new IDXL_Comm(tag,context);
00186 else
00187 currentComm->reset(tag,context);
00188 return 27;
00189 }
00190 IDXL_Comm *IDXL_Chunk::lookupComm(IDXL_Comm_t uc,const char *callingRoutine)
00191 {
00192 if (uc!=27) CkAbort("Invalid idxl_comm id");
00193 return currentComm;
00194 }
00195
00196 IDXL_Comm::IDXL_Comm(int tag_,int context) {
00197 reset(tag_,context);
00198 }
00199 void IDXL_Comm::reset(int tag_,int context) {
00200 tag=tag_;
00201 if (context==0) comm=MPI_COMM_WORLD;
00202 else comm=(MPI_Comm)context;
00203 sto.resize(0);
00204 nMsgs=0;
00205
00206
00207 msgReq.resize(0);
00208 msgSts.resize(0);
00209
00210 isPost=false;
00211 isDone=false;
00212 }
00213 IDXL_Comm::~IDXL_Comm() {
00214 for (int i=0;i<msg.size();i++)
00215 delete msg[i];
00216 }
00217
00218
00219
00220 void IDXL_Comm::send(const IDXL_Side *idx,const IDXL_Layout *dtype,const void *src)
00221 {
00222 if (isPost) CkAbort("Cannot call IDXL_Comm_send after IDXL_Comm_flush!");
00223 sto.push_back(sto_t(idx,dtype,(void *)src,send_t));
00224 }
00225 void IDXL_Comm::recv(const IDXL_Side *idx,const IDXL_Layout *dtype,void *dest)
00226 {
00227 if (isPost) CkAbort("Cannot call IDXL_Comm_recv after IDXL_Comm_flush!");
00228 sto.push_back(sto_t(idx,dtype,dest,recv_t));
00229 }
00230 void IDXL_Comm::sum(const IDXL_Side *idx,const IDXL_Layout *dtype,void *srcdest)
00231 {
00232 if (isPost) CkAbort("Cannot call IDXL_Comm_sum after IDXL_Comm_flush!");
00233 sto.push_back(sto_t(idx,dtype,srcdest,sum_t));
00234 }
00235
00236 void IDXL_Comm::post(void) {
00237 if (isPost) CkAbort("Cannot post the same IDXL_Comm_t more than once");
00238 isPost=true;
00239
00240
00241 nMsgs=0;
00242 for (int s=0;s<sto.size();s++) {
00243 const IDXL_Side *idx=sto[s].idx;
00244 const IDXL_Layout *dtype=sto[s].dtype;
00245 for (int ll=0;ll<idx->size();ll++) {
00246 const IDXL_List &l=idx->getLocalList(ll);
00247
00248
00249 ++nMsgs;
00250 if (nMsgs>msg.size()) {
00251 msg.resize(nMsgs);
00252 msg[nMsgs-1]=new msg_t;
00253 }
00254 msg_t *m=msg[nMsgs-1];
00255 m->sto=&sto[s];
00256 m->ll=ll;
00257
00258
00259 int len=l.size()*dtype->compressedBytes();
00260 m->allocate(len);
00261
00262
00263 MPI_Request req;
00264 switch (sto[s].op) {
00265 case send_t:
00266 sto[s].dtype->gather(l.size(),l.getVec(),sto[s].data,m->getBuf());
00267 MPI_Isend(m->getBuf(),len,MPI_BYTE,l.getDest(),tag,comm,&req);
00268 break;
00269 case recv_t:case sum_t:
00270 MPI_Irecv(m->getBuf(),len,MPI_BYTE,l.getDest(),tag,comm,&req);
00271 break;
00272 };
00273 msgReq.push_back(req);
00274 }
00275 }
00276 }
00277
00278 void IDXL_Comm::wait(void) {
00279 if (!isPosted()) post();
00280 CkAssert(msg.size()>=nMsgs);
00281 CkAssert(msgReq.size()==nMsgs);
00282 if (nMsgs == 0) { isDone=true; return; }
00283 msgSts.resize(nMsgs);
00284 MPI_Waitall(nMsgs,&msgReq[0],&msgSts[0]);
00285
00286 for (int im=0;im<nMsgs;im++) {
00287 msg_t *m=msg[im];
00288 sto_t *s=m->sto;
00289 const IDXL_List &l=s->idx->getLocalList(m->ll);
00290 switch (s->op) {
00291 case send_t:
00292 break;
00293 case recv_t:
00294 s->dtype->scatter(l.size(),l.getVec(),m->getBuf(),s->data);
00295 break;
00296 case sum_t:
00297 s->dtype->scatteradd(l.size(),l.getVec(),m->getBuf(),s->data);
00298 break;
00299 };
00300 }
00301 isDone=true;
00302 }
00303
00304 void IDXL_Chunk::waitComm(IDXL_Comm *comm)
00305 {
00306 comm->wait();
00307 }
00308