NEURON
bbsdirectmpi.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <nrnmpi.h>
3 #include "bbsconf.h"
4 #ifdef NRNMPI // to end of file
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <InterViews/resource.h>
9 #include "oc2iv.h"
10 #include "bbs.h"
11 #include "bbsdirect.h"
12 #include "bbssrv2mpi.h"
13 #include "bbssrv.h"
14 
15 extern void nrnmpi_int_broadcast(int*, int, int);
16 
17 #if defined(HAVE_STL)
18 #if defined(HAVE_SSTREAM) // the standard ...
19 #include <map>
20 #else
21 #include <pair.h>
22 #include <map.h>
23 #endif
24 
25 #define debug 0
26 
27 struct ltint {
28  bool operator()(int i, int j) const {
29  return i < j;
30  }
31 };
32 
33 class KeepArgs: public std::map<int, bbsmpibuf*, ltint> {};
34 
35 #endif
36 
37 
41  }
42  sendbuf_ = nil;
43  recvbuf_ = nil;
45 #if defined(HAVE_STL)
46  keepargs_ = new KeepArgs();
47 #endif
48 }
49 
51  nrnmpi_unref(sendbuf_);
52  nrnmpi_unref(recvbuf_);
53 #if defined(HAVE_STL)
54  delete keepargs_;
55 #endif
56 }
57 
58 void BBSDirect::perror(const char* s) {
59  printf("BBSDirect error %s\n", s);
60 }
61 
62 void BBSDirect::context() {
64  nrnmpi_enddata(sendbuf_);
66 
67  // if nhost > 1 of the id_bbs==0 subworld,
68  // then id > 0 need to execute the context statement
69  // but id == 0 does not.
71  size_t n;
72  bbsmpibuf* rsav = recvbuf_; // May naturally be NULL anyway
73  recvbuf_ = nrnmpi_newbuf(sendbuf_->size);
74  nrnmpi_ref(recvbuf_);
75  nrnmpi_copy(recvbuf_, sendbuf_);
76  nrnmpi_upkbegin(recvbuf_);
77  nrnmpi_upkint(recvbuf_);
78  nrnmpi_upkint(recvbuf_); // slot reserved for tag
79  execute_helper(&n, -1, false);
80  nrnmpi_unref(recvbuf_);
81  recvbuf_ = rsav;
82  }
83 
84  nrnmpi_unref(sendbuf_);
85  sendbuf_ = nil;
86 }
87 
88 int BBSDirect::upkint() {
89  int i;
90  i = nrnmpi_upkint(recvbuf_);
91 #if debug
92  printf("upkint returning %d\n", i);
93 #endif
94  return i;
95 }
96 
97 double BBSDirect::upkdouble() {
98  double x;
99  x = nrnmpi_upkdouble(recvbuf_);
100 #if debug
101  printf("upkdouble returning %g\n", x);
102 #endif
103  return x;
104 }
105 
106 void BBSDirect::upkvec(int n, double* x) {
107  nrnmpi_upkvec(n, x, recvbuf_);
108 }
109 
110 char* BBSDirect::upkstr() {
111  char* s;
112  s = nrnmpi_upkstr(recvbuf_);
113 #if debug
114  printf("upkstr returning |%s|\n", s);
115 #endif
116  return s;
117 }
118 
119 char* BBSDirect::upkpickle(size_t* n) {
120  char* s;
121  s = nrnmpi_upkpickle(n, recvbuf_);
122 #if debug
123  printf("upkpickle returning %d bytes\n", *n);
124 #endif
125  return s;
126 }
127 
128 void BBSDirect::pkbegin() {
129 #if debug
130  printf("%d BBSDirect::pkbegin\n", nrnmpi_myid_bbs);
131 #endif
132  nrnmpi_unref(sendbuf_);
133  sendbuf_ = nrnmpi_newbuf(100);
134  nrnmpi_ref(sendbuf_);
135  nrnmpi_pkbegin(sendbuf_);
136 }
137 
138 void BBSDirect::pkint(int i) {
139 #if debug
140  printf("%d BBSDirect::pkint %d\n", nrnmpi_myid_bbs, i);
141 #endif
142  nrnmpi_pkint(i, sendbuf_);
143 }
144 
145 void BBSDirect::pkdouble(double x) {
146 #if debug
147  printf("%d BBSDirect::pkdouble\n", nrnmpi_myid_bbs, x);
148 #endif
149  nrnmpi_pkdouble(x, sendbuf_);
150 }
151 
152 void BBSDirect::pkvec(int n, double* x) {
153 #if debug
154  printf("%d BBSDirect::pkvec n=%d\n", nrnmpi_myid_bbs, n);
155 #endif
156  nrnmpi_pkvec(n, x, sendbuf_);
157 }
158 
159 void BBSDirect::pkstr(const char* s) {
160 #if debug
161  printf("%d BBSDirect::pkstr %s\n", nrnmpi_myid_bbs, s);
162 #endif
163  nrnmpi_pkstr(s, sendbuf_);
164 }
165 
166 void BBSDirect::pkpickle(const char* s, size_t n) {
167 #if debug
168  printf("%d BBSDirect::pkpickle %d bytes\n", nrnmpi_myid_bbs, n);
169 #endif
170  nrnmpi_pkpickle(s, n, sendbuf_);
171 }
172 
173 void BBSDirect::post(const char* key) {
174 #if debug
175  printf("%d BBSDirect::post |%s|\n", nrnmpi_myid_bbs, key);
176 #endif
177  nrnmpi_enddata(sendbuf_);
178  nrnmpi_pkstr(key, sendbuf_);
179  BBSDirectServer::server_->post(key, sendbuf_);
180  nrnmpi_unref(sendbuf_);
181  sendbuf_ = nil;
183 }
184 
185 void BBSDirect::post_todo(int parentid) {
186 #if debug
187  printf("%d BBSDirect::post_todo for %d\n", nrnmpi_myid_bbs, parentid);
188 #endif
189  nrnmpi_enddata(sendbuf_);
190  nrnmpi_pkint(parentid, sendbuf_);
191  BBSDirectServer::server_->post_todo(parentid, nrnmpi_myid_bbs, sendbuf_);
192  nrnmpi_unref(sendbuf_);
193  sendbuf_ = nil;
195 }
196 
197 void BBSDirect::post_result(int id) {
198 #if debug
199  printf("%d BBSDirect::post_result %d\n", nrnmpi_myid_bbs, id);
200 #endif
201  nrnmpi_enddata(sendbuf_);
202  nrnmpi_pkint(id, sendbuf_);
203  BBSDirectServer::server_->post_result(id, sendbuf_);
204  nrnmpi_unref(sendbuf_);
205  sendbuf_ = nil;
207 }
208 
211  int id = BBSDirectServer::server_->look_take_todo(&recvbuf_);
212  if (id) {
213  nrnmpi_upkbegin(recvbuf_);
214 
215 #if debug
216  printf("%d look_take_todo getid=%d\n", nrnmpi_getid(recvbuf_));
217 #endif
218  }
219 #if debug
220  printf("%d BBSDirect::look_take_todo id=%d\n", nrnmpi_myid_bbs, id);
221 #endif
222  return id;
223 }
224 
225 int BBSDirect::take_todo() {
226  int id = BBSDirectServer::server_->look_take_todo(&recvbuf_);
227  if (id == 0) {
228  printf("BBSDirect::take_todo blocking\n");
229  assert(0);
230  }
231 #if debug
232  printf("%d BBSDirect::take_todo id=%d\n", nrnmpi_myid_bbs, id);
233 #endif
234  return id;
235 }
236 
237 int BBSDirect::look_take_result(int pid) {
239  int id = BBSDirectServer::server_->look_take_result(pid, &recvbuf_);
240 #if debug
241  printf("%d BBSDirect::look_take_result id=%d pid=%d\n", nrnmpi_myid_bbs, id, pid);
242 #endif
243  if (id) {
244  nrnmpi_upkbegin(recvbuf_);
245  }
246 #if debug
247  printf("%d look_take_result return id=%d\n", nrnmpi_myid_bbs, id);
248 #endif
249  return id;
250 }
251 
252 int BBSDirect::master_take_result(int pid) {
253  assert(is_master());
255  for (;;) {
256  int id = look_take_result(pid);
257  if (id) {
258  return id;
259  }
260  // wait for a message (no MPI_Iprobe)
262  }
263 }
264 
265 void BBSDirect::save_args(int userid) {
266 #if defined(HAVE_STL)
267  nrnmpi_ref(sendbuf_);
268  keepargs_->insert(std::pair<const int, bbsmpibuf*>(userid, sendbuf_));
269 
270 #endif
272 }
273 
274 void BBSDirect::return_args(int userid) {
275 #if defined(HAVE_STL)
276  KeepArgs::iterator i = keepargs_->find(userid);
277  nrnmpi_unref(recvbuf_);
278  recvbuf_ = nil;
279  if (i != keepargs_->end()) {
280  recvbuf_ = (*i).second;
281  keepargs_->erase(i);
282  nrnmpi_upkbegin(recvbuf_);
284  }
285 #endif
286 }
287 
288 bool BBSDirect::look_take(const char* key) {
290  bool b = BBSDirectServer::server_->look_take(key, &recvbuf_);
291  if (b) {
292  nrnmpi_upkbegin(recvbuf_);
293  }
294 #if debug
295  if (b) {
296  printf("look_take |%s| true\n", key);
297  } else {
298  printf("look_take |%s| false\n", key);
299  }
300 #endif
301  return b;
302 }
303 
304 bool BBSDirect::look(const char* key) {
306  bool b = BBSDirectServer::server_->look(key, &recvbuf_);
307  if (b) {
308  nrnmpi_upkbegin(recvbuf_);
309  }
310 #if debug
311  printf("look |%s| %d\n", key, b);
312 #endif
313  return b;
314 }
315 
316 void BBSDirect::take(const char* key) { // blocking
317  int id;
318  double st = time();
319  for (;;) {
320  if (look_take(key)) {
321  wait_time_ += time() - st;
322  return;
323  } else if (!master_works_) {
325  } else if ((id = look_take_todo()) != 0) {
326  wait_time_ += time() - st;
327  execute(id);
328  st = time();
329  } else {
330  // perhaps should do something meaningful here
331  // like check whether to quit or not
332  }
333  }
334 }
335 
336 void BBSDirect::done() {
337  // printf("%d bbsdirect::done\n", nrnmpi_myid_world);
338  int i;
339  if (done_) {
340  return;
341  }
343  int info[2];
344  info[0] = -2;
345  info[1] = -1;
346  // printf("%d broadcast %d %d\n", nrnmpi_myid_world, info[0], info[1]);
347  nrnmpi_int_broadcast(info, 2, 0);
348  }
349  BBSImpl::done();
350  done_ = true;
351  nrnmpi_unref(sendbuf_);
352  sendbuf_ = nrnmpi_newbuf(20);
353 #if debug
354  printf("done: numprocs_bbs=%d\n", nrnmpi_numprocs_bbs);
355 #endif
356  for (i = 1; i < nrnmpi_numprocs_bbs; ++i) {
357  nrnmpi_bbssend(i, QUIT, sendbuf_);
358  // printf("kill %d\n", i);
359  }
361 }
362 
363 void BBSDirect::start() {
364  if (started_) {
365  return;
366  }
367  BBSImpl::start();
368  is_master_ = true;
370  bbs_handle();
371 }
372 
373 #endif // NRNMPI
#define nil
Definition: enter-scope.h:36
#define QUIT
Definition: bbssrv.h:4
virtual int look_take_result(int pid)
virtual void start()
virtual void return_args(int)
virtual char * upkpickle(size_t *)
virtual char * upkstr()
virtual void pkint(int)
KeepArgs * keepargs_
Definition: bbsdirect.h:58
virtual void post_result(int id)
virtual void save_args(int)
virtual void pkbegin()
virtual void upkvec(int, double *)
virtual int master_take_result(int pid)
virtual void post(const char *)
virtual void pkpickle(const char *, size_t)
virtual void post_todo(int parentid)
virtual void pkdouble(double)
virtual void pkstr(const char *)
virtual void take(const char *)
virtual int upkint()
virtual double upkdouble()
virtual bool look_take(const char *)
virtual void context()
virtual void pkvec(int, double *)
virtual ~BBSDirect()
virtual void done()
virtual bool look(const char *)
virtual int take_todo()
virtual void perror(const char *)
virtual int look_take_todo()
int look_take_result(int parentid)
bool look(const char *key)
void context(int ncid, int *cids)
bool look_take(const char *key)
static void handle()
void post_todo(int parentid, int cid)
void post(const char *key)
static BBSDirectServer * server_
Definition: bbslsrv2.h:18
void post_result(int id)
static void handle_block()
int working_id_
Definition: bbsimpl.h:54
static bool is_master_
Definition: bbsimpl.h:60
virtual void return_args(int userid)
Definition: ocbbs.cpp:1385
char * execute_helper(size_t *, int id, bool exec=true)
Definition: ocbbs.cpp:1215
static bool master_works_
Definition: bbsimpl.h:64
virtual void execute(int id)
Definition: bbs.cpp:282
static bool started_
Definition: bbsimpl.h:61
double wait_time_
Definition: bbsimpl.h:55
virtual bool is_master()
Definition: bbs.cpp:125
virtual double time()
Definition: bbs.cpp:133
static bool done_
Definition: bbsimpl.h:61
virtual void start()
Definition: bbs.cpp:506
virtual void done()
Definition: bbs.cpp:487
#define assert(ex)
Definition: hocassrt.h:32
void bbs_handle()
Definition: datapath.cpp:33
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
static double map(void *v)
Definition: mlinedit.cpp:47
#define printf
Definition: mwprefix.h:26
static List * info
int const size_t const size_t n
Definition: nrngsl.h:11
size_t j
int nrnmpi_numprocs_world
int nrnmpi_numprocs
int nrnmpi_numprocs_bbs
int nrnmpi_myid_bbs
static double userid(void *v)
Definition: ocbbs.cpp:227
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
#define key
Definition: spt2queue.cpp:20