mpiUtil.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // mpiUtil.h
00012 //
00013 // Jonathan Eckstein
00014 //
00021 #ifdef __GNUC__
00022 #pragma interface
00023 #endif
00024 
00025 #ifndef __mpiUtil_H
00026 #define __mpiUtil_H
00027 
00028 #include "utilib_dll.h"
00029 #include "errmsg.h"
00030 #include "_generic.h"
00031 #include "logEvent.h"
00032 
00033 #ifdef USING_MPI
00034 #include "mpi.h"
00035 
00036 //
00037 // To compile code for logging of all messages.
00038 //
00039 #ifdef EVENT_LOGGING_PRESENT
00040 
00041 #include "paramTable.h"
00042 
00043 #define LOG_SEND(a,b,c,d)   if (messageLog()) logSend(a,b,c,d)
00044 #define LOG_RECV(s)         if (messageLog()) logRecv(s)
00045 
00046 #else
00047 
00048 #define LOG_SEND(a,b,c,d)               // Nothing
00049 #define LOG_RECV(s)                     // Nothing
00050 
00051 #endif
00052 
00053 
00054 class UTILIB_API uMPI 
00055 {
00056 public:
00057 
00059   static MPI_Comm comm;
00061   static int rank;
00063   static int size;
00068   static int ioProc;
00070   static int iDoIO;
00071 
00073   static int errorCode;
00074 
00075 #ifdef EVENT_LOGGING_PRESENT
00076 
00077   CLASS_PARAMETER(messageLog);
00078 
00080   static void logSend(int dest,int tag,int count,MPI_Datatype t);
00082   static void logRecv(MPI_Status* status);
00083 
00084 #endif
00085   
00087   static int running()
00088     {
00089       int running;
00090       MPI_Initialized(&running);
00091       return(running);
00092     };
00093 
00099   static int packSlop(int m)
00100     {
00101       return 2*m + 32;
00102     };
00103 
00105   static int sizeOf(MPI_Datatype t);
00106 
00108   static void init(int* argcP,char*** argv, MPI_Comm comm_=MPI_COMM_WORLD);
00109   
00111   static void done();
00112 
00114   static void barrier()
00115     {
00116       errorCode = MPI_Barrier(comm);
00117       if (errorCode)
00118         Warning(errmsg("MPI_Barrier failed, code %d",errorCode));
00119     }
00120 
00121 
00123   static void reduce(void* sendbuf,void* recvbuf,int count,
00124                      MPI_Datatype datatype,MPI_Op op,int root)
00125     {
00126       errorCode = MPI_Reduce(sendbuf,recvbuf,count,datatype,op,root,
00127                              comm);
00128       if (errorCode)
00129         Warning(errmsg("MPI_Reduce failed, code %d",errorCode));
00130     };
00131 
00132 
00134   static int sum(int value,int root = ioProc)
00135     {
00136       int result = 0;
00137       errorCode = MPI_Reduce(&value,&result,1,MPI_INT,MPI_SUM,root,
00138                              comm);
00139       if (errorCode)
00140         Warning(errmsg("MPI_Reduce failed, code %d",errorCode));
00141       return result;
00142     };
00143 
00144 
00146   static double sum(double value,int root = ioProc)
00147     {
00148       double result = 0;
00149       errorCode = MPI_Reduce(&value,&result,1,MPI_DOUBLE,MPI_SUM,root,
00150                              comm);
00151       if (errorCode)
00152         Warning(errmsg("MPI_Reduce failed, code %d",errorCode));
00153       return result;
00154     };
00155 
00156 
00158   static int max(int value,int root = ioProc)
00159     {
00160       int result = 0;
00161       errorCode = MPI_Reduce(&value,&result,1,MPI_INT,MPI_MAX,root,
00162                              comm);
00163       if (errorCode)
00164         Warning(errmsg("MPI_Reduce failed, code %d",errorCode));
00165       return result;
00166     };
00167 
00168 
00170   static double max(double value,int root = ioProc)
00171     {
00172       double result = 0;
00173       errorCode = MPI_Reduce(&value,&result,1,MPI_DOUBLE,MPI_MAX,root,
00174                              comm);
00175       if (errorCode)
00176         Warning(errmsg("MPI_Reduce failed, code %d",errorCode));
00177       return result;
00178     };
00179 
00180 
00182   static void broadcast(void* buffer,int count,MPI_Datatype datatype,int root)
00183     {
00184       errorCode = MPI_Bcast(buffer,count,datatype,root,comm);
00185       if (errorCode)
00186         Warning(errmsg("MPI_Broadcast failed, code %d",errorCode));
00187     };
00188 
00189 
00191   static void reduceCast(void* sendbuf,void* recvbuf,int count,
00192                          MPI_Datatype datatype,MPI_Op op)
00193     {
00194       reduce(sendbuf,recvbuf,count,datatype,op,0);
00195       broadcast(recvbuf,count,datatype,0);
00196     };
00197       
00198 
00200   static void isend(void* buffer,int count,MPI_Datatype datatype,int dest,
00201                     int tag,MPI_Request* request)
00202     {
00203       LOG_SEND(dest,tag,count,datatype);
00204       errorCode = MPI_Isend(buffer,count,datatype,dest,tag,comm,
00205                             request);
00206       if (errorCode)
00207         Warning(errmsg("MPI_Isend failed, code %d",errorCode));
00208     };
00209 
00210 
00215   static void isend(void* buffer,int count,MPI_Datatype datatype,int dest,
00216                     int tag)
00217     {
00218       MPI_Request request;
00219       isend(buffer,count,datatype,dest,tag,&request);
00220       requestFree(&request);
00221     };
00222 
00223 
00225   static void send(void* buffer,int count,MPI_Datatype datatype,int dest,
00226                    int tag)
00227     {
00228       LOG_SEND(dest,tag,count,datatype);
00229       errorCode = MPI_Send(buffer,count,datatype,dest,tag,comm);
00230       if (errorCode)
00231         Warning(errmsg("MPI_Send failed, code %d",errorCode));
00232     }
00233       
00234 
00236   static void requestFree(MPI_Request* request)
00237     {
00238       errorCode = MPI_Request_free(request);
00239       if (errorCode)
00240         Warning(errmsg("MPI_Request_free failed, code %d",errorCode));
00241     };
00242 
00243 
00245   static void issend(void* buffer,int count,MPI_Datatype datatype,int dest,
00246                      int tag,MPI_Request* request)
00247     {
00248       LOG_SEND(dest,tag,count,datatype);
00249       errorCode = MPI_Issend(buffer,count,datatype,dest,tag,comm,
00250                              request);
00251       if (errorCode)
00252         Warning(errmsg("MPI_Issend failed, code %d",errorCode));
00253     };
00254 
00255 
00257   static void irecv(void* buffer,int count,MPI_Datatype datatype,int source,
00258                     int tag,MPI_Request* request)
00259     {
00260       errorCode = MPI_Irecv(buffer,count,datatype,source,tag,comm,
00261                             request);
00262       if (errorCode)
00263         Warning(errmsg("MPI_Irecv failed, code %d",errorCode));
00264     };
00265 
00266 
00268   static void recv(void* buffer,int count,MPI_Datatype datatype,int source,
00269                    int tag,MPI_Status* status)
00270     {
00271       errorCode = MPI_Recv(buffer,count,datatype,source,tag,comm,
00272                             status);
00273       if (errorCode)
00274         Warning(errmsg("MPI_Recv failed, code %d",errorCode));
00275       LOG_RECV(status);
00276     };
00277 
00278 
00280   static int getCount(MPI_Status* status,MPI_Datatype datatype)
00281     {
00282       int count;
00283       errorCode = MPI_Get_count(status,datatype,&count);
00284       if (errorCode)
00285         Warning(errmsg("MPI_Get_count failed, code %d",errorCode));
00286       return count;
00287     };
00288   
00289 
00291   static void test(MPI_Request* request,int* flag,MPI_Status* status)
00292     {
00293       errorCode = MPI_Test(request,flag,status);
00294       if (errorCode)
00295         Warning(errmsg("MPI_Test failed, code %d",errorCode));
00296 #ifdef EVENT_LOGGING_PRESENT
00297       if (*flag)
00298         LOG_RECV(status);
00299 #endif
00300     };
00301 
00303   static int test(MPI_Request* request,MPI_Status* status)
00304     {
00305       int flag;
00306       test(request,&flag,status);
00307       return flag;
00308     };
00309 
00311   static int test(MPI_Request* request)
00312     {
00313       MPI_Status status;
00314       return test(request,&status);
00315     };
00316 
00318   static int testsome(int incount, MPI_Request* request_array,
00319                 int& outcount, int* array_of_indeces, MPI_Status* status_array)
00320     {
00321       errorCode = MPI_Testsome(incount,request_array,&outcount,
00322                                 array_of_indeces,status_array);
00323       if (errorCode != MPI_SUCCESS)
00324         Warning(errmsg("MPI_Testsome failed, code %d",errorCode));
00325 #ifdef EVENT_LOGGING_PRESENT
00326       for(int i=0; i<outcount; i++)
00327         LOG_RECV(status_array+i);
00328 #endif
00329       return (outcount > 0);
00330     };
00331 
00333   static void cancel(MPI_Request* request)
00334     {
00335 #ifndef COUGAR
00336       errorCode = MPI_Cancel(request);
00337       if (errorCode)
00338         Warning(errmsg("MPI_Cancel failed, code %d",errorCode));
00339 #else
00340       Warning("uMPI::cancel - MPI_Cancel is not yet implemented");
00341 #endif
00342     };
00343 
00344 
00346   static void wait(MPI_Request* request,MPI_Status* status)
00347     {
00348       errorCode = MPI_Wait(request,status);
00349       if (errorCode)
00350         Warning(errmsg("MPI_Wait failed, code %d",errorCode));
00351       LOG_RECV(status);
00352     };
00353 
00354 
00356   static void killSendRequest(MPI_Request* request);
00358   static void killRecvRequest(MPI_Request* request);
00359 
00360 };
00361 
00362 
00363 #else
00364 
00365 
00366 //  If no MPI, don't define anything except running(), which returns FALSE.
00367 
00368 class uMPI 
00369 {
00370 public:
00371   static int running() { return FALSE; };
00372 };
00373  
00374 
00375 #endif
00376 
00377 #endif