MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
proc1.cpp
Go to the documentation of this file.
1 /*
2 void process( const Eref& e, ProcPtr p )
3 {
4  for ( unsigned int i = 0; i < numNodes; ++i ){
5  if ( i != myNode ) {
6  isend( outbuf_[i] );
7 
8  inbufNum = recv(from anywhere)
9  readBuf( inbuf_[inbufNum] );
10  }
11  }
12 }
13 
14 vector< vector< double > > outBuf_; // outbuf[tgtnode][data]
15 vector< vector< double > > inBuf_;// inbuf[srcnode][data]
16 
17 
18 // Things to monitor:
19 // - The send happens with a standard buf size, and if the contents
20 // exceed it there is a signal to this effect and the rest of it is sent
21 // right away as a big block.
22 // - The Recv likewise
23 //
24 // mpi_testsome checks which msgs have been received.
25 //
26 //
27 
28 // Assumes we already have an irecv out for all the nodes.
29 //
30 void checkIncoming()
31 {
32  MPI_request* array_of_requests;
33  MPI_status* array_of_statuses;
34 
35  MPI_testsome()
36  int MPI_Testsome(int incount, MPI_Request array_of_requests[],
37  int *outcount, int array_of_indices[], MPI_Status array_of_statuses[])
38 
39  for ( unsigned int
40 
41  MPI_Irecv (&buf,count,datatype,source,tag,comm,&request)
42 }
43 
44 
45 main()
46 {
47 }
48 */
49 
50 #include <mpi.h>
51 #include <vector>
52 using namespace std;
53 
54 #define WORKTAG 1
55 #define DIETAG 2
56 
57 
58 /* Local functions */
59 
60 const int numEntries = 10;
61 const int totCalls = 1000;
62 static void master(void);
63 static void slave(void);
64 static double* get_next_work_item()
65 {
66 
67  static vector< double > ret( numEntries );
68  static unsigned int numCalls = 0;
69  for ( unsigned int i = 0; i < numEntries; ++i )
70  ret[i] = i + numCalls;
71 
72  numCalls++;
73  if ( numCalls > totCalls )
74  return 0;
75  return &ret[0];
76 }
77 
78 static double do_work(double* work);
79 
80 int main(int argc, char **argv)
81 {
82  int myrank;
83 
84  /* Initialize MPI */
85 
86  MPI_Init(&argc, &argv);
87 
88  /* Find out my identity in the default communicator */
89 
90  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
91  if (myrank == 0) {
92  master();
93  } else {
94  slave();
95  }
96 
97  /* Shut down MPI */
98 
99  MPI_Finalize();
100  return 0;
101 }
102 
103 
104 
105 static void
106 master(void)
107 {
108  int ntasks, rank;
109  double* work;
110  double result;
111  MPI_Status status;
112  double tot = 0.0;
113  double tc = totCalls;
114  double ne = numEntries;
115  double expectedTot =
116  tc * ( ( ne * (ne - 1.0) )/2.0 ) +
117  ne * ( tc * (tc - 1.0) )/2.0;
118 
119  /* Find out how many processes there are in the default
120  communicator */
121 
122  MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
123 
124  /* Seed the slaves; send one unit of work to each slave. */
125 
126  for (rank = 1; rank < ntasks; ++rank) {
127 
128  /* Find the next item of work to do */
129 
130  work = get_next_work_item();
131 
132  /* Send it to each rank */
133 
134  MPI_Send(work, /* message buffer */
135  numEntries, /* one data item */
136  MPI_DOUBLE, /* data item is a double */
137  rank, /* destination process rank */
138  WORKTAG, /* user chosen message tag */
139  MPI_COMM_WORLD); /* default communicator */
140  }
141 
142  /* Loop over getting new work requests until there is no more work
143  to be done */
144 
145  work = get_next_work_item();
146  while (work != NULL) {
147 
148  /* Receive results from a slave */
149 
150  MPI_Recv(&result, /* message buffer */
151  1, /* one data item */
152  MPI_DOUBLE, /* of type double real */
153  MPI_ANY_SOURCE, /* receive from any sender */
154  MPI_ANY_TAG, /* any type of message */
155  MPI_COMM_WORLD, /* default communicator */
156  &status); /* info about the received message */
157 
158  /* Send the slave a new work unit */
159 
160  MPI_Send(work, /* message buffer */
161  numEntries, /* one data item */
162  MPI_DOUBLE, /* data item is an integer */
163  status.MPI_SOURCE, /* to who we just received from */
164  WORKTAG, /* user chosen message tag */
165  MPI_COMM_WORLD); /* default communicator */
166 
167  /* Get the next unit of work to be done */
168 
169  work = get_next_work_item();
170  tot += result;
171  }
172 
173  /* There's no more work to be done, so receive all the outstanding
174  results from the slaves. */
175 
176  for (rank = 1; rank < ntasks; ++rank) {
177  MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
178  MPI_ANY_TAG, MPI_COMM_WORLD, &status);
179  tot += result;
180  }
181 
182  /* Tell all the slaves to exit by sending an empty message with the
183  DIETAG. */
184 
185  for (rank = 1; rank < ntasks; ++rank) {
186  MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD);
187  }
188  cout << "Tot = " << tot << ", expected = " << expectedTot << endl;
189 }
190 
191 
192 static void
193 slave(void)
194 {
195  double work[numEntries];
196  double result;
197  MPI_Status status;
198 
199  while (1) {
200 
201  /* Receive a message from the master */
202 
203  MPI_Recv( work, numEntries, MPI_DOUBLE, 0, MPI_ANY_TAG,
204  MPI_COMM_WORLD, &status);
205 
206  /* Check the tag of the received message. */
207 
208  if (status.MPI_TAG == DIETAG) {
209  return;
210  }
211 
212  /* Do the work */
213 
214  result = do_work(work);
215 
216  /* Send the result back */
217 
218  MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
219  }
220 }
221 
222 static double
223 do_work(double* work)
224 {
225  double tot = 0;
226  for (int i =0; i < numEntries; ++i )
227  tot += work[i];
228 }
#define WORKTAG
Definition: proc1.cpp:54
const int numEntries
Definition: proc1.cpp:60
int main(int argc, char **argv)
Definition: proc1.cpp:80
static double do_work(double *work)
Definition: proc1.cpp:223
static double * get_next_work_item()
Definition: proc1.cpp:64
static void slave(void)
Definition: proc1.cpp:193
static void master(void)
Definition: proc1.cpp:106
#define DIETAG
Definition: proc1.cpp:55
const int totCalls
Definition: proc1.cpp:61