00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __PARAMS_MPI_DATA_TRANSFER_
00010 #define __PARAMS_MPI_DATA_TRANSFER_
00011
00012 #include "mpi.h"
00013 #include "std_cpp_includes.hh"
00014 #include "mpiutils.hh"
00015 #include "except.hh"
00016
00017 namespace RVL {
00018
00021 template<typename Scalar>
00022 inline static MPI_Datatype findMPIDatatype() {
00023 RVLException e;
00024 e<<"Error: call to base findMPIDatatype template - undefined \n";
00025 throw e;
00026 }
00027
00028 template<>
00029 inline MPI_Datatype findMPIDatatype<char>() {return MPI_CHAR;}
00030
00031 template<>
00032 inline MPI_Datatype findMPIDatatype<short>() {return MPI_SHORT;}
00033
00034 template<>
00035 inline MPI_Datatype findMPIDatatype<int>() {return MPI_INT;}
00036
00037 template<>
00038 inline MPI_Datatype findMPIDatatype<long>() {return MPI_LONG;}
00039
00040 template<>
00041 inline MPI_Datatype findMPIDatatype<unsigned char>() {return MPI_UNSIGNED_CHAR;}
00042
00043 template<>
00044 inline MPI_Datatype findMPIDatatype<unsigned short>() {return MPI_UNSIGNED_SHORT;}
00045
00046 template<>
00047 inline MPI_Datatype findMPIDatatype<unsigned int>() {return MPI_UNSIGNED;}
00048
00049 template<>
00050 inline MPI_Datatype findMPIDatatype<unsigned long>() {return MPI_UNSIGNED_LONG;}
00051
00052 template<>
00053 inline MPI_Datatype findMPIDatatype<float>() {return MPI_FLOAT;}
00054
00055 template<>
00056 inline MPI_Datatype findMPIDatatype<double>() {return MPI_DOUBLE;}
00057
00058 template<>
00059 inline MPI_Datatype findMPIDatatype<long double>() {return MPI_LONG_DOUBLE;}
00060
00063 template<typename T>
00064 void Build_MPI_Datatype(MPI_Datatype * mpitype) {
00065 try {
00066 *mpitype=findMPIDatatype<T>();
00067 }
00068 catch (RVLException & e) {
00069 e<<"\ncalled from BuildMPI_Datatype\n";
00070 throw e;
00071 }
00072 }
00073
00079 template<typename T>
00080 class MPI_Sender {
00081
00082 private:
00083
00084 int dest;
00085 MPI_Comm comm;
00086
00087 public:
00088
00089 MPI_Sender(int _dest=0, MPI_Comm _comm = MPI_COMM_WORLD)
00090 : dest(_dest), comm(_comm) {}
00091 MPI_Sender(MPI_Sender<T> const & s)
00092 : dest(s.dest), comm(s.comm) {}
00093 ~MPI_Sender() {}
00094
00095 bool setDestination( int d ){ return MPIRVL_SetRank(dest,d,comm); }
00096
00097 bool operator()(T & x) const {
00098 try {
00099 int tag=0;
00100 MPI_Datatype dt;
00101 Build_MPI_Datatype<T>(&dt);
00102 if (MPI_SUCCESS == MPI_Send(&x,1,dt,dest,tag,comm)) return true;
00103 return false;
00104 }
00105 catch (RVLException & e) {
00106 e<<"\ncalled from MPI_Sender::operator()\n";
00107 throw e;
00108 }
00109 }
00110 };
00111
00112 template<typename T>
00113 class MPI_Receiver {
00114
00115 MPI_Status * status;
00116 int src;
00117 MPI_Comm comm;
00118
00119 public:
00120
00121 MPI_Receiver(MPI_Status * _status,
00122 int _src=0,
00123 MPI_Comm _comm = MPI_COMM_WORLD)
00124 : status(_status), src(_src), comm(_comm) {}
00125 MPI_Receiver(MPI_Receiver<T> const & s)
00126 : status(s.status),src(s.src), comm(s.comm) {}
00127 ~MPI_Receiver() {}
00128
00129 bool setSource( int s ){ return MPIRVL_SetRank(src,s,comm); }
00130
00131 bool operator()(T & x) const {
00132 try {
00133 int tag=0;
00134 MPI_Datatype dt;
00135 Build_MPI_Datatype<T>(&dt);
00136 if (MPI_SUCCESS == MPI_Recv(&x,1,dt,src,tag,comm,status)) return true;
00137 return false;
00138 }
00139 catch (RVLException & e) {
00140 e<<"\ncalled from MPI_Receiver::operator()\n";
00141 throw e;
00142 }
00143 }
00144 };
00145
00146 template<typename T>
00147 class MPI_Broadcaster {
00148
00149 int root;
00150 MPI_Comm comm;
00151
00152 public:
00153
00154 MPI_Broadcaster(int _root=0, MPI_Comm _comm = MPI_COMM_WORLD)
00155 : root(_root), comm(_comm) {
00156 int rt;
00157 if (!MPIRVL_SetRank(rt,root,comm)) {
00158 RVLException e;
00159 e<<"Error: MPI_Broadcaster constructor\n";
00160 e<<"root outside range of ranks for assigned MPI_Comm\n";
00161 throw e;
00162 }
00163 }
00164 MPI_Broadcaster(MPI_Broadcaster<T> const & b)
00165 : root(b.root), comm(b.comm) {}
00166 ~MPI_Broadcaster() {}
00167
00168 bool operator()(T & x) const {
00169 try {
00170 MPI_Datatype dt;
00171 Build_MPI_Datatype<T>(&dt);
00172 if (MPI_SUCCESS == MPI_Bcast(&x,1,dt,root,comm)) return true;
00173 return false;
00174 }
00175 catch (RVLException & e) {
00176 e<<"\ncalled from MPI_Broadcaster::operator()\n";
00177 throw e;
00178 }
00179 }
00180 };
00181
00182 template<typename T>
00183 class MPI_Reducer {
00184
00185 MPI_Op op;
00186 int root;
00187 MPI_Comm comm;
00188
00189 public:
00190
00191 MPI_Reducer(MPI_Op _op= MPI_SUM,
00192 int _root=0,
00193 MPI_Comm _comm = MPI_COMM_WORLD)
00194 : op(_op), root(_root), comm(_comm) {
00195 int rt;
00196 if (!MPIRVL_SetRank(rt,root,comm)) {
00197 RVLException e;
00198 e<<"Error: MPI_Reducer constructor\n";
00199 e<<"root outside range of ranks for assigned MPI_Comm\n";
00200 throw e;
00201 }
00202 }
00203 MPI_Reducer(MPI_Reducer<T> const & b)
00204 : op(b.op), root(b.root), comm(b.comm) {}
00205 ~MPI_Reducer() {}
00206
00207 bool operator()(T & xout, T const & xin) const {
00208 try {
00209 MPI_Datatype dt;
00210 Build_MPI_Datatype<T>(&dt);
00211 if (MPI_SUCCESS == MPI_Reduce(&xin,&xout,1,dt,op,root,comm)) return true;
00212 return false;
00213 }
00214 catch (RVLException & e) {
00215 e<<"\ncalled from MPI_Reducer::operator()\n";
00216 throw e;
00217 }
00218 }
00219 };
00220
00221 }
00222
00223 #endif // __PARAMS_MPI_DATA_TRANSFER_