Sandia Home Sandia Home
Main Page | Publications | Downloads | Configuration | Running the Code | Solver Parameters | FAQ | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

cex_executor.cpp

Go to the documentation of this file.
00001 
00007 #include "mpi.h"
00008 #include "msgtags.hpp"
00009 #include "executor.hpp"
00010 
00011 CustomExecutor::CustomExecutor(int n_in, int nprocs_in) : 
00012   n(n_in), nprocs(nprocs_in), status(nprocs,0)
00013 {
00014   // Allocate memory for x
00015   x = new double(n);
00016 
00017   // First processor is always busy because it's me!
00018   status[0] = 1;
00019 }
00020 
00021 CustomExecutor::~CustomExecutor()
00022 {
00023   delete x;
00024 }
00025 
00026 bool CustomExecutor::isWaiting() const
00027 {
00028   for (int i = 1; i < nprocs; i ++)
00029     if (status[i] == 0)
00030       return true;
00031 
00032   return false;
00033 }
00034 
00035 bool CustomExecutor::spawn(const APPSPACK::Vector& x_in, int tag_in)
00036 {
00037   // Find a free worker (we assume that there must be one because
00038   // isWaiting should have already been called).
00039   int idx = -1;
00040   for (int i = 1; i < nprocs; i ++)
00041     if (status[i] == 0)
00042     {
00043       idx = i;
00044       break;
00045     }
00046 
00047   if (idx == -1)
00048     return false;
00049 
00050   // Copy x
00051   for (int i = 0; i < n; i ++)
00052     x[i] = x_in[i];
00053 
00054   // Send tag and x to processor idx
00055   MPI_Send(&tag_in, 1, MPI_INT, idx, XTAG, MPI_COMM_WORLD);
00056   MPI_Send(x, n, MPI_DOUBLE, idx, XVEC, MPI_COMM_WORLD);
00057 
00058   // Mark the worker as busy
00059   status[idx] = 1;
00060 
00061   return true;
00062 }
00063 
00064 int CustomExecutor::recv(int& tag_out, 
00065                          APPSPACK::Vector& f_out, 
00066                          string& msg_out)
00067 {
00068   // Check to see if a new message is waiting
00069   MPI_Status mpiStatus;
00070   int flag;
00071 
00072   // Non-block probe to check for incoming message
00073   // NOTE: Cannot use a blocking probe here
00074   MPI_Iprobe(MPI_ANY_SOURCE, XTAG, MPI_COMM_WORLD, &flag, &mpiStatus);
00075 
00076   // Return zero if there is no message
00077   if (flag == 0)
00078     return 0;
00079 
00080   // Get the source of the message
00081   int source = mpiStatus.MPI_SOURCE;
00082 
00083   // Unpack the message
00084   int tag;
00085   int code;
00086   double f;
00087   MPI_Recv(&tag, 1, MPI_INT, source, XTAG, MPI_COMM_WORLD, &mpiStatus);
00088   MPI_Recv(&code, 1, MPI_INT, source, CODE, MPI_COMM_WORLD, &mpiStatus);
00089   MPI_Recv(&f, 1, MPI_DOUBLE, source, FVAL, MPI_COMM_WORLD, &mpiStatus);
00090 
00091   // Interpret the result
00092   if (code == 0)
00093   {
00094     tag_out = tag;
00095     f_out.resize(0);
00096     msg_out = "constraint violation";
00097   }
00098   else
00099   {
00100     tag_out = tag;
00101     f_out.resize(1);
00102     f_out[0] = f;
00103     msg_out = "success";
00104   }
00105 
00106   // Mark the worker as free
00107   status[source] = 0;
00108 
00109   // Important to return a non-zero to indicate that the recv was successful
00110   return source;
00111 }
00112 
00113 void CustomExecutor::print() const
00114 {
00115   cout << "Custom MPI executor with " << (nprocs - 1) << " workers" << endl;
00116 }

 

© Sandia Corporation | Site Contact | Privacy and Security

Generated on Fri Feb 16 10:33:35 2007 for APPSPACK 5.0.1 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2002