//////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008 The Regents of the University of California // // This file is part of Qbox // // Qbox is distributed under the terms of the GNU General Public License // as published by the Free Software Foundation, either version 2 of // the License, or (at your option) any later version. // See the file COPYING in the root directory of this distribution // or . // //////////////////////////////////////////////////////////////////////////////// // // Context.C // //////////////////////////////////////////////////////////////////////////////// #include "Context.h" #include #include #include #include #include #include #include "blacs.h" #include using namespace std; //////////////////////////////////////////////////////////////////////////////// ContextRep::ContextRep(MPI_Comm comm) : ictxt_(-1), myrow_(-1), mycol_(-1) { // construct a single-row Context int nprocs; char order='R'; MPI_Comm_dup(comm,&comm_); MPI_Comm_size(comm_,&nprocs); MPI_Comm_rank(comm_,&mype_); ictxt_ = Csys2blacs_handle(comm_); nprow_ = 1; npcol_ = nprocs; Cblacs_gridinit( &ictxt_, &order, nprow_, npcol_ ); // get values of nprow_, npcol_, myrow_ and mycol_ in the new context if ( ictxt_ >= 0 ) Cblacs_gridinfo(ictxt_, &nprow_, &npcol_, &myrow_, &mycol_); size_ = nprow_ * npcol_; myproc_ = myrow_ < 0 ? -1 : mycol_ + npcol_ * myrow_; onpe0_ = ( mype_ == 0 ); active_ = ( ictxt_ >= 0 ); pmap_.resize(size_); for ( int i = 0; i < size_; i++ ) pmap_[i] = i; MPI_Group group_world, subgroup; MPI_Comm_group(comm,&group_world); MPI_Group_incl(group_world,size_,&pmap_[0],&subgroup); MPI_Comm_create(comm,subgroup,&comm_); MPI_Group_free(&group_world); MPI_Group_free(&subgroup); } //////////////////////////////////////////////////////////////////////////////// ContextRep::ContextRep(MPI_Comm comm, int nprow, int npcol) : ictxt_(-1), myrow_(-1), mycol_(-1), nprow_(nprow), npcol_(npcol) { int nprocs; char order = 'C'; MPI_Comm_dup(comm,&comm_); MPI_Comm_size(comm_,&nprocs); MPI_Comm_rank(comm_,&mype_); ictxt_ = Csys2blacs_handle(comm_); if ( nprocs < nprow * npcol ) { cout << " nprocs=" << nprocs << endl; cout << " Context nprow*npcol > nprocs" << endl; Cblacs_abort(ictxt_, 1); } Cblacs_gridinit( &ictxt_, &order, nprow, npcol ); // get values of nprow_, npcol_, myrow_ and mycol_ in the new context if ( ictxt_ >= 0 ) Cblacs_gridinfo(ictxt_, &nprow_, &npcol_, &myrow_, &mycol_); size_ = nprow_ * npcol_; myproc_ = Cblacs_pnum(ictxt_,myrow_,mycol_); onpe0_ = ( mype_ == 0 ); active_ = ( ictxt_ >= 0 ); pmap_.resize(size_); // column-major order int i = 0; for ( int ic = 0; ic < npcol; ic++ ) for ( int ir = 0; ir < nprow; ir++ ) { pmap_[ir+nprow*ic] = i; i++; } MPI_Group group_world, subgroup; MPI_Comm_group(comm,&group_world); MPI_Group_incl(group_world,size_,&pmap_[0],&subgroup); MPI_Comm_create(comm,subgroup,&comm_); MPI_Group_free(&group_world); MPI_Group_free(&subgroup); } //////////////////////////////////////////////////////////////////////////////// ContextRep::~ContextRep() { if ( myrow_ != -1 ) { // cout << " ContextRep destructor called on ictxt = " << ictxt_ << endl; Cblacs_gridexit( ictxt_ ); MPI_Comm_free(&comm_); } } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dsend(int m, int n, double* a, int lda, int rdest, int cdest) const { Cdgesd2d(ictxt_,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::drecv(int m, int n, double* a, int lda, int rsrc, int csrc) const { Cdgerv2d(ictxt_,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dsum(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { Cdgsum2d(ictxt_,&scope,&topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dmax(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { Cdgamx2d(ictxt_,&scope,&topology,m,n,a,lda,(int*)0,(int*)0,-1,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dmax(char scope, char topology, int m, int n, double* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { Cdgamx2d(ictxt_,&scope,&topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dmin(char scope, char topology, int m, int n, double* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { Cdgamn2d(ictxt_,&scope,&topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dmin(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { Cdgamn2d(ictxt_,&scope,&topology,m,n,a,lda,(int*)0,(int*)0,-1,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dbcast_send(char scope, char topology, int m, int n, double* a,int lda) const { Cdgebs2d(ictxt_,&scope,&topology,m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::dbcast_recv(char scope, char topology, int m, int n, double* a, int lda, int rsrc, int csrc) const { Cdgebr2d(ictxt_,&scope,&topology,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::isend(int m, int n, int* a, int lda, int rdest, int cdest) const { Cigesd2d(ictxt_,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::irecv(int m, int n, int* a, int lda, int rsrc, int csrc) const { Cigerv2d(ictxt_,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::isum(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { Cigsum2d(ictxt_,&scope,&topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::imax(char scope, char topology, int m, int n, int* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { Cigamx2d(ictxt_,&scope,&topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::imax(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { Cigamx2d(ictxt_,&scope,&topology,m,n,a,lda,(int*)0,(int*)0,-1,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::imin(char scope, char topology, int m, int n, int* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { Cigamn2d(ictxt_,&scope,&topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::imin(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { Cigamn2d(ictxt_,&scope,&topology,m,n,a,lda,(int*)0,(int*)0,-1,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::ibcast_send(char scope, char topology, int m, int n, int* a,int lda) const { Cigebs2d(ictxt_,&scope,&topology,m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::ibcast_recv(char scope, char topology, int m, int n, int* a, int lda, int rsrc, int csrc) const { Cigebr2d(ictxt_,&scope,&topology,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void ContextRep::string_send(std::string& s, int rdest, int cdest) const { int len = s.size(); isend(1,1,&len,1,rdest,cdest); int ilen = len/(sizeof(int)/sizeof(char)); if ( len%(sizeof(int)/sizeof(char)) != 0 ) ilen++; int* ibuf = new int[ilen]; s.copy((char*)ibuf,std::string::npos); isend(ilen,1,ibuf,ilen,rdest,cdest); delete [] ibuf; } //////////////////////////////////////////////////////////////////////////////// void ContextRep::string_recv(std::string& s, int rsrc, int csrc) const { int len = -1; irecv(1,1,&len,1,rsrc,csrc); int ilen = len/(sizeof(int)/sizeof(char)); if ( len%(sizeof(int)/sizeof(char)) != 0 ) ilen++; int* ibuf = new int[ilen]; irecv(ilen,1,ibuf,ilen,rsrc,csrc); s.resize(len); s.assign((char*)ibuf,len); delete [] ibuf; } //////////////////////////////////////////////////////////////////////////////// void ContextRep::string_bcast(std::string& s, int isrc) const { int len; if ( mype() == isrc ) { len = s.length(); } MPI_Bcast(&len,1,MPI_INT,isrc,comm()); char* buf = new char[len+1]; // s is initialized only on task isrc if ( mype() == isrc ) { s.copy(buf,std::string::npos); buf[len]=0; assert(buf[len]=='\0'); } MPI_Bcast(buf,len+1,MPI_CHAR,isrc,comm()); s = buf; delete [] buf; } //////////////////////////////////////////////////////////////////////////////// void ContextRep::print(ostream& os) const { if ( active_ ) { os << " " << nprow_ << "x" << npcol_ << " "; os << "{ "; for ( int ir = 0; ir < nprow_; ir++ ) { os << "{ "; for ( int ic = 0; ic < npcol_; ic++ ) { os << pmap_[ir+nprow_*ic] << " "; } os << "} "; } //os << "} (ictxt=" << ictxt_ << ")" << endl; os << "} (ictxt=" << ictxt_ << ")"; int handle; Cblacs_get(ictxt_,10,&handle); os << "(handle=" << handle << ")"; os << "(comm=" << comm_<< ")" << endl; } else { os << " (inactive)" << endl; } } //////////////////////////////////////////////////////////////////////////////// int Context::ictxt() const { return rep->ictxt(); } //////////////////////////////////////////////////////////////////////////////// int Context::myrow() const { return rep->myrow(); } //////////////////////////////////////////////////////////////////////////////// int Context::mycol() const { return rep->mycol(); } //////////////////////////////////////////////////////////////////////////////// int Context::nprow() const { return rep->nprow(); } //////////////////////////////////////////////////////////////////////////////// int Context::npcol() const { return rep->npcol(); } //////////////////////////////////////////////////////////////////////////////// int Context::size() const { return rep->size(); } //////////////////////////////////////////////////////////////////////////////// int Context::myproc() const { return rep->myproc(); } //////////////////////////////////////////////////////////////////////////////// int Context::mype() const { return rep->mype(); } //////////////////////////////////////////////////////////////////////////////// int Context::pmap(int irow, int icol) const { return rep->pmap(irow,icol); } //////////////////////////////////////////////////////////////////////////////// bool Context::onpe0(void) const { return rep->onpe0(); } //////////////////////////////////////////////////////////////////////////////// bool Context::active(void) const { return rep->active(); } //////////////////////////////////////////////////////////////////////////////// void Context::abort(int ierr) const { rep->abort(ierr); } //////////////////////////////////////////////////////////////////////////////// void Context::barrier(void) const { rep->barrier(); } //////////////////////////////////////////////////////////////////////////////// void Context::barrier(char scope) const { rep->barrier(scope); } //////////////////////////////////////////////////////////////////////////////// void Context::dsend(int m, int n, double* a, int lda, int rdest, int cdest) const { rep->dsend(m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::drecv(int m, int n, double* a, int lda, int rsrc, int csrc) const { rep->drecv(m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::dsum(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { rep->dsum(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::dsum(char scope, int m, int n, double* a, int lda) const { rep->dsum(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dsum(int m, int n, double* a, int lda) const { rep->dsum('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dmax(char scope, char topology, int m, int n, double* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { rep->dmax(scope,topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::dmax(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { rep->dmax(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::dmax(char scope, int m, int n, double* a, int lda) const { rep->dmax(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dmax(int m, int n, double* a, int lda) const { rep->dmax('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dmin(char scope, char topology, int m, int n, double* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { rep->dmin(scope,topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::dmin(char scope, char topology, int m, int n, double* a, int lda, int rdest, int cdest) const { rep->dmin(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::dmin(char scope, int m, int n, double* a, int lda) const { rep->dmin(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dmin(int m, int n, double* a, int lda) const { rep->dmin('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_send(char scope, char topology, int m, int n, double* a, int lda) const { rep->dbcast_send(scope,topology,m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_send(char scope, int m, int n, double* a, int lda) const { rep->dbcast_send(scope,' ',m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_send(int m, int n, double* a, int lda) const { rep->dbcast_send('A',' ',m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_recv(char scope, char topology, int m, int n, double* a, int lda, int rsrc,int csrc) const { rep->dbcast_recv(scope,topology,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_recv(char scope, int m, int n, double* a, int lda, int rsrc, int csrc) const { rep->dbcast_recv(scope,' ',m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::dbcast_recv(int m, int n, double* a, int lda, int rsrc,int csrc) const { rep->dbcast_recv('A',' ',m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::isend(int m, int n, int* a, int lda, int rdest, int cdest) const { rep->isend(m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::irecv(int m, int n, int* a, int lda, int rsrc, int csrc) const { rep->irecv(m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::isum(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { rep->isum(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::isum(char scope, int m, int n, int* a, int lda) const { rep->isum(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::isum(int m, int n, int* a, int lda) const { rep->isum('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::imax(char scope, char topology, int m, int n, int* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { rep->imax(scope,topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::imax(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { rep->imax(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::imax(char scope, int m, int n, int* a, int lda) const { rep->imax(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::imax(int m, int n, int* a, int lda) const { rep->imax('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::imin(char scope, char topology, int m, int n, int* a, int lda, int* ra, int* ca, int rcflag, int rdest, int cdest) const { rep->imin(scope,topology,m,n,a,lda,ra,ca,rcflag,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::imin(char scope, char topology, int m, int n, int* a, int lda, int rdest, int cdest) const { rep->imin(scope,topology,m,n,a,lda,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::imin(char scope, int m, int n, int* a, int lda) const { rep->imin(scope,' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::imin(int m, int n, int* a, int lda) const { rep->imin('A',' ',m,n,a,lda,-1,-1); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_send(char scope, char topology, int m, int n, int* a, int lda) const { rep->ibcast_send(scope,topology,m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_send(char scope, int m, int n, int* a, int lda) const { rep->ibcast_send(scope,' ',m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_send(int m, int n, int* a, int lda) const { rep->ibcast_send('A',' ',m,n,a,lda); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_recv(char scope, char topology, int m, int n, int* a, int lda, int rsrc,int csrc) const { rep->ibcast_recv(scope,topology,m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_recv(char scope, int m, int n, int* a, int lda, int rsrc, int csrc) const { rep->ibcast_recv(scope,' ',m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::ibcast_recv(int m, int n, int* a, int lda, int rsrc,int csrc) const { rep->ibcast_recv('A',' ',m,n,a,lda,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::string_send(std::string& s, int rdest, int cdest) const { rep->string_send(s,rdest,cdest); } //////////////////////////////////////////////////////////////////////////////// void Context::string_recv(std::string& s, int rsrc, int csrc) const { rep->string_recv(s,rsrc,csrc); } //////////////////////////////////////////////////////////////////////////////// void Context::string_bcast(std::string& s, int isrc) const { rep->string_bcast(s,isrc); } //////////////////////////////////////////////////////////////////////////////// bool Context::operator==(const Context& ctxt) const { return ( rep->ictxt() == ctxt.ictxt() ); } //////////////////////////////////////////////////////////////////////////////// MPI_Comm Context::comm(void) const { return rep->comm(); } //////////////////////////////////////////////////////////////////////////////// void Context::print(ostream& os) const { rep->print(os);} //////////////////////////////////////////////////////////////////////////////// ostream& operator<<(ostream& os, const Context& c) { c.print(os); return os; }