Kokkos Node API and Local Linear Algebra Kernels Version of the Day
Tsqr_TeuchosMessenger.hpp
00001 //@HEADER
00002 // ************************************************************************
00003 // 
00004 //          Kokkos: Node API and Parallel Node Kernels
00005 //              Copyright (2009) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ************************************************************************
00027 //@HEADER
00028 
00029 #ifndef __TSQR_TeuchosMessenger_hpp
00030 #define __TSQR_TeuchosMessenger_hpp
00031 
00032 #include <Teuchos_CommHelpers.hpp>
00033 #include <Tsqr_MessengerBase.hpp>
00034 
00035 #include <algorithm>
00036 
00037 
00038 namespace TSQR { 
00039 
00050   template<class Datum>
00051   class TeuchosMessenger : public MessengerBase<Datum> {
00052   public:
00053     typedef Teuchos::RCP<const Teuchos::Comm<int> > comm_ptr;
00054 
00056     TeuchosMessenger (const comm_ptr& pComm) : pComm_ (pComm) {}
00057 
00059     virtual ~TeuchosMessenger() {}
00060 
00067     void 
00068     send (const Datum sendData[], 
00069     const int sendCount, 
00070     const int destProc, 
00071     const int tag) 
00072     {
00073       // NOTE (mfh 14 June 2010): Teuchos generates "tag" arguments to
00074       // MPI calls internally, so we ignore the tag here.  I don't use
00075       // tags for anything in TSQR, so it doesn't matter.
00076       Teuchos::send (*pComm_, sendCount, sendData, destProc);
00077     }
00078 
00085     void 
00086     recv (Datum recvData[], 
00087     const int recvCount, 
00088     const int srcProc, 
00089     const int tag) 
00090     {
00091       // NOTE (mfh 14 June 2010): Teuchos generates "tag" arguments to
00092       // MPI calls internally, so we ignore the tag here.  I don't use
00093       // tags for anything in TSQR, so it doesn't matter.
00094       Teuchos::receive (*pComm_, srcProc, recvCount, recvData);
00095     }
00096 
00115     void 
00116     swapData (const Datum sendData[], 
00117         Datum recvData[], 
00118         const int sendRecvCount, 
00119         const int destProc, 
00120         const int tag)
00121     {
00122       if (destProc == rank())
00123   {
00124     // If the sending and receiving processes are the same,
00125     // then all we need to do is copy the data.  Hopefully in
00126     // that case you aren't aliasing.  std::copy assumes that
00127     // the third argument does not point to an element in the
00128     // range of the first two arguments.
00129     std::copy (sendData, sendData+sendRecvCount, recvData);
00130   }
00131       else
00132   {
00133     using Teuchos::RCP;
00134     using Teuchos::ArrayRCP;
00135     using Teuchos::CommRequest;
00136 
00137     const int srcProc = Teuchos::rank (*pComm_);
00138 
00139     // If we can prove that sendData and recvData don't alias
00140     // one another, use an isend and an ireceive to exchange
00141     // them.  (Our test may not necessarily be safe in general,
00142     // since we only check whether the pointers are equal and
00143     // not whether the arrays overlap.  However, it is safe for
00144     // the specific case of TSQR.)
00145     //
00146     // Otherwise, if the arrays do alias one another, safely
00147     // perform a send and then a receive (or a receive and then
00148     // a send, depending on whether this MPI process is the
00149     // source or destination process).  
00150     //
00151     // (It would be nice if Teuchos had a sendRecv() routine, as
00152     // of summer 2010 when this code was written.  As it stands,
00153     // we have to do a send and then a receive.)
00154     if (sendData == recvData)
00155       {
00156         // The smaller-rank process sends first, and the
00157         // larger-rank process receives first.
00158         //
00159         // Teuchos::send() and Teuchos::recv() are blocking,
00160         // so we may safely write to recvBuf even if it
00161         // aliases sendBuf.
00162         if (srcProc < destProc)
00163     {
00164       Teuchos::send (*pComm_, sendRecvCount, sendData, destProc);
00165       Teuchos::receive (*pComm_, destProc, sendRecvCount, recvData);
00166     }
00167         else 
00168     {
00169       Teuchos::receive (*pComm_, destProc, sendRecvCount, recvData);
00170       Teuchos::send (*pComm_, sendRecvCount, sendData, destProc);
00171     }
00172       }
00173     else
00174       {
00175         ArrayRCP<const Datum> sendBuf (sendData, 0, sendRecvCount, false);
00176         ArrayRCP<Datum> recvBuf (recvData, 0, sendRecvCount, false);
00177 
00178         RCP<CommRequest> sendReq, recvReq;
00179         if (srcProc < destProc)
00180     {
00181       sendReq = Teuchos::isend (*pComm_, sendBuf, destProc);
00182       recvReq = Teuchos::ireceive (*pComm_, recvBuf, destProc);
00183     }
00184         else
00185     {
00186       recvReq = Teuchos::ireceive (*pComm_, recvBuf, destProc);
00187       sendReq = Teuchos::isend (*pComm_, sendBuf, destProc);
00188     }
00189         // Wait on both the send and the receive to complete.  The
00190         // two can happen independently, because sendBuf and recvBuf
00191         // are different.  (We assert no aliasing of buffers here,
00192         // and we've also checked above that destProc != rank().)
00193         Teuchos::waitAll (*pComm_, Teuchos::tuple (sendReq, recvReq));
00194       }
00195   }
00196     }
00197 
00199     Datum 
00200     globalSum (const Datum& inDatum) 
00201     {
00202       Datum outDatum;
00203       Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_SUM, inDatum, 
00204         Teuchos::outArg(outDatum));
00205       return outDatum;
00206     }
00207 
00211     Datum 
00212     globalMin (const Datum& inDatum)
00213     {
00214       Datum outDatum;
00215       Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_MIN, inDatum, 
00216         Teuchos::outArg(outDatum));
00217       return outDatum;
00218     }
00219 
00223     Datum 
00224     globalMax (const Datum& inDatum)
00225     {
00226       Datum outDatum;
00227       Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_MAX, inDatum, 
00228         Teuchos::outArg(outDatum));
00229       return outDatum;
00230     }
00231 
00233     void
00234     globalVectorSum (const Datum inData[], 
00235          Datum outData[], 
00236          const int count) 
00237     {
00238       Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_SUM, count, 
00239         inData, outData);
00240     }
00241 
00243     void
00244     broadcast (Datum data[], 
00245          const int count,
00246          const int root)
00247     {
00248       Teuchos::broadcast (*pComm_, root, count, data);
00249     }
00250 
00252     int rank () const { return Teuchos::rank (*pComm_); }
00253 
00255     int size () const { return Teuchos::size (*pComm_); }
00256 
00258     void barrier () const { Teuchos::barrier (*pComm_); }
00259 
00260   private:
00261 
00263     comm_ptr pComm_;
00264   };
00265 } // namespace TSQR
00266 
00267 #endif // __TSQR_TeuchosMessenger_hpp
00268 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends